From 97c992ad447d1ea29233b3eae977518fd6cf272c Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Thu, 15 Oct 2026 14:34:46 +0200 Subject: [PATCH] =?UTF-8?q?v0.314.0:=20the=20R-1060=20web=20test=20(a=20fa?= =?UTF-8?q?ke=20Plex=20that=20refuses=20the=20name=20=E2=80=9Eplex?= =?UTF-8?q?=E2=80=9D),=20left=20out=20of=2017863fe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS --- .../web/r1060_plex_by_address_test.go | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 controller/internal/web/r1060_plex_by_address_test.go diff --git a/controller/internal/web/r1060_plex_by_address_test.go b/controller/internal/web/r1060_plex_by_address_test.go new file mode 100644 index 0000000..ac46bf5 --- /dev/null +++ b/controller/internal/web/r1060_plex_by_address_test.go @@ -0,0 +1,67 @@ +package web + +import ( + "context" + "net" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "gitea.dooplex.hu/admin/felhom-controller/internal/mediawire" +) + +// fakePlex answers as Plex does (measured on demo-hp 9201, 2026-10-15): a Host that is not an address is „non-local", +// so the claim gets 401; by address the claim is taken (200 here — the real one asks plex.tv). The test client dials +// this server whatever the URL names, so the only difference between the two calls is the Host header. +func fakePlex(t *testing.T) (hosts *[]string) { + t.Helper() + var seen []string + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + seen = append(seen, r.Host) + h, _, err := net.SplitHostPort(r.Host) + if err != nil { + h = r.Host + } + local := net.ParseIP(h) != nil + switch r.URL.Path { + case "/myplex/claim": + if !local { + w.WriteHeader(http.StatusUnauthorized) + return + } + w.WriteHeader(http.StatusOK) + case "/identity": + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"MediaContainer":{"claimed":` + map[bool]string{true: "true", false: "false"}[local] + `}}`)) + default: + w.WriteHeader(http.StatusNotFound) + } + })) + t.Cleanup(srv.Close) + oldHTTP, oldLookup := plexHTTP, mediawire.PlexLookup + plexHTTP = &http.Client{Transport: &http.Transport{DialContext: func(ctx context.Context, network, _ string) (net.Conn, error) { + return (&net.Dialer{}).DialContext(ctx, network, srv.Listener.Addr().String()) + }}} + mediawire.PlexLookup = func(context.Context) ([]net.IPAddr, error) { return []net.IPAddr{{IP: net.ParseIP("10.9.8.7")}}, nil } + t.Cleanup(func() { plexHTTP, mediawire.PlexLookup = oldHTTP, oldLookup }) + return &seen +} + +// R-1060 — the household's claim reaches Plex BY ADDRESS, so Plex takes it as local; the identity call too. +// COMPANION RED-PROOF: make mediawire.PlexURL return "http://plex:" (today's call) → 401 and this fails. +func TestR1060_TheClaimReachesPlexByAddress(t *testing.T) { + hosts := fakePlex(t) + code, err := plexClaim("claim-felhomtestcode0000") + if err != nil || code != http.StatusOK { + t.Fatalf("claim → %d (%v); Plex refuses the name „plex” as non-local — the box must call it by address", code, err) + } + if !plexClaimed() { + t.Fatal("the identity call did not reach Plex as local") + } + for _, h := range *hosts { + if !strings.HasPrefix(h, "10.9.8.7:") { + t.Errorf("a call to Plex carried Host %q, not its address", h) + } + } +}