package main import ( "database/sql" "net/http" "net/http/httptest" "strings" "testing" "bookmarkmanager/backend/internal/store" ) func getCover(t *testing.T, srv http.Handler, path string, cookie *http.Cookie) *httptest.ResponseRecorder { t.Helper() req := httptest.NewRequest(http.MethodGet, path, nil) if cookie != nil { req.AddCookie(cookie) } rr := httptest.NewRecorder() srv.ServeHTTP(rr, req) return rr } // The acquired Cover is served from this deployment's own origin, to any // browser rendering a third-party page — no session, no credential (ADR-0007). func TestPublicCoverServesStoredBytesUnauthenticated(t *testing.T) { const sourceURL = "https://cdn.asurascans.com/covers/solo.webp" srv, st := newWebTestServer(t, testConfig()) if err := st.PutCover(sourceURL, []byte("\x00webp-bytes"), "image/webp"); err != nil { t.Fatalf("PutCover: %v", err) } // The wire URL is what a client actually requests, so the path under test // is taken from it rather than rebuilt by hand. wire := st.CoverWireURL(store.CoverAddressForBytes([]byte("\x00webp-bytes"))) path, ok := strings.CutPrefix(wire, testCoverBaseURL) if !ok { t.Fatalf("wire URL %q is not on the public origin %q", wire, testCoverBaseURL) } rr := getCover(t, srv, path, nil) if rr.Code != http.StatusOK { t.Fatalf("status = %d, want 200 without any credential", rr.Code) } if got := rr.Body.String(); got != "\x00webp-bytes" { t.Fatalf("body = %q, want the stored bytes", got) } if got := rr.Header().Get("Content-Type"); got != "image/webp" { t.Fatalf("Content-Type = %q, want the stored one", got) } // Content-addressed bytes never change, so a client that has them must // never need to ask again. if got := rr.Header().Get("Cache-Control"); !strings.Contains(got, "immutable") { t.Fatalf("Cache-Control = %q, want an immutable cache directive", got) } } func TestPublicCoverRejectsUnknownAddress(t *testing.T) { srv, _ := newWebTestServer(t, testConfig()) cases := map[string]string{ "unknown": "/covers/" + store.CoverAddressForBytes([]byte("never-stored")), "malformed": "/covers/not-an-address", "traversal": "/covers/../../etc/passwd", "empty": "/covers/", } for name, path := range cases { t.Run(name, func(t *testing.T) { if rr := getCover(t, srv, path, nil); rr.Code == http.StatusOK { t.Fatalf("%s: status = 200, want anything but a served body", path) } }) } } // A content type outside the image set is never echoed back. The old kagane // proxy could fetch text/html from a challenged fetch and had to refuse it; // the general route's only input is the store, and the store refuses to // record anything that is not an image — but the guarantee is pinned at the // serving boundary, not the write gate, so a poisoned row (migrated data, a // writer that skips the gate) is also never served. func TestPublicCoverNeverEchoesNonImage(t *testing.T) { const sourceURL = "https://cdn.example/cover" st, dsn := newTestStoreURL(t) // The write gate refuses non-image content types outright. if err := st.PutCover(sourceURL, []byte("