Failing tests for the missing validation on the encrypted-URL path and the token generator: an encrypted token carrying an over-limit dimension or an unrecognized fit mode must be rejected with 400, and POST /generate with a non-numeric or over-limit width must return 400 rather than minting a token. Also covers the shared imgcache validator directly. Model: opus-4-8
99 lines
2.6 KiB
Go
99 lines
2.6 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
|
|
"sneak.berlin/go/pixa/internal/encurl"
|
|
"sneak.berlin/go/pixa/internal/imgcache"
|
|
)
|
|
|
|
// newEncTestServer builds a router serving the encrypted-URL route with a
|
|
// generator seeded by the shared test signing key. The image service is left
|
|
// nil: these tests exercise validation that rejects a token before any image
|
|
// is fetched, so the handler must never reach the service.
|
|
func newEncTestServer(t *testing.T) (*encurl.Generator, http.Handler) {
|
|
t.Helper()
|
|
|
|
encGen, err := encurl.NewGenerator(testSigningKey)
|
|
if err != nil {
|
|
t.Fatalf("encurl.NewGenerator() error = %v", err)
|
|
}
|
|
|
|
h := &Handlers{
|
|
log: slog.New(slog.DiscardHandler),
|
|
encGen: encGen,
|
|
}
|
|
|
|
r := chi.NewRouter()
|
|
r.Get("/v1/e/{token}/*", h.HandleImageEnc())
|
|
|
|
return encGen, r
|
|
}
|
|
|
|
// getEncToken issues a GET for the given token and returns the recorder.
|
|
func getEncToken(srv http.Handler, token string) *httptest.ResponseRecorder {
|
|
req := httptest.NewRequestWithContext(
|
|
context.Background(), http.MethodGet, "/v1/e/"+token+"/img.jpg", nil)
|
|
rec := httptest.NewRecorder()
|
|
srv.ServeHTTP(rec, req)
|
|
|
|
return rec
|
|
}
|
|
|
|
// TestHandleImageEnc_OverLimitDimension_Returns400 verifies that a decrypted
|
|
// token requesting a dimension beyond MaxDimension is rejected with 400
|
|
// instead of reaching the image processor and libvips.
|
|
func TestHandleImageEnc_OverLimitDimension_Returns400(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
encGen, srv := newEncTestServer(t)
|
|
|
|
token, err := encGen.Generate(&encurl.Payload{
|
|
SourceHost: "cdn.example.com",
|
|
SourcePath: "/photo.jpg",
|
|
Width: 100000,
|
|
Height: 100000,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Generate() error = %v", err)
|
|
}
|
|
|
|
rec := getEncToken(srv, token)
|
|
|
|
if rec.Code != http.StatusBadRequest {
|
|
t.Fatalf("status = %d, want %d", rec.Code, http.StatusBadRequest)
|
|
}
|
|
}
|
|
|
|
// TestHandleImageEnc_InvalidFitMode_Returns400 verifies that a decrypted token
|
|
// carrying an unrecognized fit mode is rejected with 400 rather than surfacing
|
|
// as a 500 from the image processor's default branch.
|
|
func TestHandleImageEnc_InvalidFitMode_Returns400(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
encGen, srv := newEncTestServer(t)
|
|
|
|
token, err := encGen.Generate(&encurl.Payload{
|
|
SourceHost: "cdn.example.com",
|
|
SourcePath: "/photo.jpg",
|
|
Width: 800,
|
|
Height: 600,
|
|
FitMode: imgcache.FitMode("bogus"),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Generate() error = %v", err)
|
|
}
|
|
|
|
rec := getEncToken(srv, token)
|
|
|
|
if rec.Code != http.StatusBadRequest {
|
|
t.Fatalf("status = %d, want %d", rec.Code, http.StatusBadRequest)
|
|
}
|
|
}
|