1 Commits
Author SHA1 Message Date
sneak 0b1113878e One image request type instead of five (closes #307)
check / check (push) Canceled after 0s
The new package internal/imagerequest holds the request type, its two
parts Source and Transform, the Format and Fit types, the dimension and
fit checks, the /v1/image/ path parsing and the variant key; it imports
no other package of pixa. imgcache.ParsedURL, imgcache.ImageRequest,
signature.Request, imageprocessor.Request, the second Size, format and
fit types and the conversions between them are gone. The image
processor takes a Transform only. encurl keeps a private struct with the
token's CBOR field names, so tokens made before still decode. VariantKey
moves with the function that makes it. Tests follow the moved code; the
tests of the removed conversions go with them.

Model: opus-5-5
2026-10-21 12:09:05 +00:00
3 changed files with 16 additions and 14 deletions
+8 -8
View File
@@ -145,7 +145,7 @@ func (s *Handlers) HandleGenerateURL() http.HandlerFunc {
return
}
payload, expiresAt, ttl, err := buildGeneratePayload(parsed, r.Form)
req, expiresAt, ttl, err := buildGenerateRequest(parsed, r.Form)
if err != nil {
s.renderGeneratorWithForm(w, r, err.Error(), r.Form,
http.StatusBadRequest)
@@ -154,8 +154,8 @@ func (s *Handlers) HandleGenerateURL() http.HandlerFunc {
}
// The image URL must fetch the source URL as it was written
payload.AllowHTTP = s.config.AllowHTTP
fetchURL := payload.SourceURL()
req.AllowHTTP = s.config.AllowHTTP
fetchURL := req.SourceURL()
if !fetchedAsWritten(parsed, fetchURL) {
s.renderGeneratorWithForm(w, r, "Source URL cannot be fetched as "+
@@ -166,7 +166,7 @@ func (s *Handlers) HandleGenerateURL() http.HandlerFunc {
}
// Generate encrypted token
token, err := s.encGen.Generate(payload)
token, err := s.encGen.Generate(req)
if err != nil {
s.log.Error("failed to generate encrypted URL", "error", err)
s.renderGeneratorWithForm(w, r, "Failed to generate URL", r.Form,
@@ -239,13 +239,13 @@ func fetchedAsWritten(source *url.URL, fetchURL string) bool {
fetched.RawQuery == source.RawQuery
}
// buildGeneratePayload parses the numeric form fields and assembles the
// buildGenerateRequest parses the numeric form fields and assembles the
// image request the encrypted URL's token is made from. ttl=0 means never
// expires (Expires stays the zero time). A non-numeric or out-of-range
// width, height, quality or ttl, or an unrecognized fit mode, is a client
// error naming the offending field. The format field is passed through
// unchecked.
func buildGeneratePayload(
func buildGenerateRequest(
parsed *url.URL, form url.Values,
) (*imagerequest.Request, time.Time, int, error) {
width, err := parseFormDimension(form, "width")
@@ -282,7 +282,7 @@ func buildGeneratePayload(
expiresAt = time.Now().Add(time.Duration(ttl) * time.Second)
}
payload := &imagerequest.Request{
req := &imagerequest.Request{
Source: imagerequest.Source{
Host: parsed.Host,
Path: parsed.Path,
@@ -297,7 +297,7 @@ func buildGeneratePayload(
Expires: expiresAt,
}
return payload, expiresAt, ttl, nil
return req, expiresAt, ttl, nil
}
// parseFormDimension reads an optional width or height form field. An empty
@@ -125,10 +125,10 @@ func TestGeneratePostRejectsBadField(t *testing.T) {
}
}
// TestBuildGeneratePayloadDefaultAndLimits verifies that an empty quality
// TestBuildGenerateRequestDefaultAndLimits verifies that an empty quality
// takes the default, and that the largest accepted width, height, quality and
// ttl are accepted with an expiry still in the future.
func TestBuildGeneratePayloadDefaultAndLimits(t *testing.T) {
func TestBuildGenerateRequestDefaultAndLimits(t *testing.T) {
t.Parallel()
parsed, err := url.Parse(testSourceURL)
@@ -136,17 +136,17 @@ func TestBuildGeneratePayloadDefaultAndLimits(t *testing.T) {
t.Fatalf("url.Parse() error = %v", err)
}
payload, _, _, err := buildGeneratePayload(parsed, url.Values{})
req, _, _, err := buildGenerateRequest(parsed, url.Values{})
if err != nil {
t.Fatalf("empty form: error = %v", err)
}
if payload.Transform.Quality != encurl.DefaultQuality {
if req.Transform.Quality != encurl.DefaultQuality {
t.Errorf("empty quality gave %d, want %d",
payload.Transform.Quality, encurl.DefaultQuality)
req.Transform.Quality, encurl.DefaultQuality)
}
_, expiresAt, _, err := buildGeneratePayload(parsed, url.Values{
_, expiresAt, _, err := buildGenerateRequest(parsed, url.Values{
widthField: {strconv.Itoa(imagerequest.MaxDimension)},
heightField: {strconv.Itoa(imagerequest.MaxDimension)},
qualityField: {strconv.Itoa(maxQuality)},
@@ -381,6 +381,7 @@ func TestService_Get_InvalidFile(t *testing.T) {
req := photoVariant(fixtures, 85, imagerequest.FitCover)
req.Source.Path = "/images/fake.jpg"
req.Transform.Size = imagerequest.Size{Width: 50, Height: 50}
// Should fail because magic bytes don't match
_, err := svc.Get(ctx, req)
@@ -397,6 +398,7 @@ func TestService_Get_NotFound(t *testing.T) {
req := photoVariant(fixtures, 85, imagerequest.FitCover)
req.Source.Path = "/images/nonexistent.jpg"
req.Transform.Size = imagerequest.Size{Width: 50, Height: 50}
_, err := svc.Get(ctx, req)
if err == nil {