package mediawire import ( "context" "fmt" "net" "strconv" "time" ) // R-1060 (v0.314.0): every call the box makes to Plex goes to its ADDRESS, never to the name „plex". // // Plex refuses a request whose Host header is a name it does not know as non-local: „Request came in with unrecognized // domain / IP 'plex' in header Host; treating as non-local" (its own log, demo-hp 9201, 2026-10-15). The claim answered // 401 in 0 ms with two fresh codes; by address the same request is local (a fake code: 500 from plex.tv; measured, // felhom.eu audits/media-build-2026-10-15/G7/G5e-host-measure.txt). The K6 spike on Tester 1 called by address and passed; // the product called by name, and its tests replaced Plex with a seam, so nothing met the refusal before a household did. // Used by all four calls: the claim and the identity (internal/web), the library wiring and the sessions (this package). // Pinned by plexaddr_test.go and internal/web/r1060_plex_by_address_test.go. // PlexLookup resolves the plex container on the docker network AT CALL TIME — never cached: a restarted container may // get another address. A seam for tests. var PlexLookup = func(ctx context.Context) ([]net.IPAddr, error) { return net.DefaultResolver.LookupIPAddr(ctx, "plex") } // PlexURL is Plex's base URL by address: http://: (IPv4 first). func PlexURL(port int) (string, error) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() addrs, err := PlexLookup(ctx) if err != nil { return "", fmt.Errorf("resolving the plex container: %w", err) } for _, a := range addrs { if ip4 := a.IP.To4(); ip4 != nil { return "http://" + net.JoinHostPort(ip4.String(), strconv.Itoa(port)), nil } } for _, a := range addrs { return "http://" + net.JoinHostPort(a.IP.String(), strconv.Itoa(port)), nil } return "", fmt.Errorf("the plex container resolves to no address") }