Failing tests for the missing validation on the encrypted-URL route and the token generator: an encrypted token carrying an over-limit dimension or an unrecognized fit mode must be rejected with 400; POST /generate with a bad width, height, quality, ttl or fit must return 400, mint no token, and name the field on the page; an empty quality takes 85 and the largest accepted values still give an expiry in the future. Also covers the shared imgcache validator and the plain image route's invalid fit mode. Model: opus-4-8 (implementation); opus-5-5 (rework)
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)
|
|
}
|
|
}
|