Posters: recognise a login page instead of an image; try the key in the query, then the provider

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 00:24:17 +02:00
co-authored by Claude Sonnet 5.5
parent 4d602b2acb
commit 2ba47cb4ee
4 changed files with 134 additions and 13 deletions
+67
View File
@@ -4,6 +4,7 @@ import (
"context"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
@@ -124,3 +125,69 @@ func TestPosterFallsBackToTheProviderWhenTheInstanceHasNoCopy(t *testing.T) {
t.Error("expected the local error")
}
}
// loginWall answers like an instance that requires a login for /MediaCover:
// a 200 with an HTML page, unless the request carries the key as a query parameter.
func loginWall(acceptQuery bool, hits *[]string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
*hits = append(*hits, r.URL.RequestURI()+" key-header="+r.Header.Get("X-Api-Key"))
if acceptQuery && r.URL.Query().Get("apikey") == "secret" {
w.Header().Set("Content-Type", "image/jpeg")
w.Write([]byte("IMAGE"))
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Write([]byte("<!DOCTYPE html><html><head><title>Login</title>"))
}
}
func TestPosterTriesTheKeyInTheQueryWhenGivenALoginPage(t *testing.T) {
var hits []string
srv := httptest.NewServer(loginWall(true, &hits))
defer srv.Close()
c := NewClient(srv.URL, "secret")
_, fetch, _ := c.Poster([]Image{{CoverType: "poster", URL: "/MediaCover/89/poster.jpg"}}, true)
data, err := fetch(context.Background())
if err != nil || string(data) != "IMAGE" {
t.Fatalf("data=%q err=%v, hits=%v", data, err, hits)
}
// Small variant with the header (a page), then the same file with the key in the query.
if len(hits) != 2 || !strings.Contains(hits[0], "poster-250.jpg") || !strings.Contains(hits[0], "key-header=secret") ||
!strings.Contains(hits[1], "poster-250.jpg?apikey=secret") {
t.Errorf("requests = %v", hits)
}
}
func TestPosterUsesTheProviderWhenTheInstanceOnlyShowsALogin(t *testing.T) {
var hits []string
instance := httptest.NewServer(loginWall(false, &hits))
defer instance.Close()
var remoteKey, remoteQuery string
remote := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
remoteKey, remoteQuery = r.Header.Get("X-Api-Key"), r.URL.RawQuery
w.Header().Set("Content-Type", "image/webp")
w.Write([]byte("WEBP"))
}))
defer remote.Close()
c := NewClient(instance.URL, "secret")
_, fetch, _ := c.Poster([]Image{{CoverType: "poster", URL: "/MediaCover/89/poster.jpg", RemoteURL: remote.URL + "/p.jpg"}}, true)
data, err := fetch(context.Background())
if err != nil || string(data) != "WEBP" {
t.Fatalf("data=%q err=%v", data, err)
}
if remoteKey != "" || remoteQuery != "" {
t.Errorf("credentials reached the provider: header %q query %q", remoteKey, remoteQuery)
}
if len(hits) != 2 { // the small variant with the header and with the query; the original is skipped
t.Errorf("instance requests = %v", hits)
}
// Without a provider address the failure says what came back.
_, fetch, _ = c.Poster([]Image{{CoverType: "poster", URL: "/MediaCover/89/poster.jpg"}}, true)
_, err = fetch(context.Background())
if err == nil || !strings.Contains(err.Error(), "text/html") || !strings.Contains(err.Error(), "login") {
t.Errorf("error = %v", err)
}
}