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 short CBOR field names. VariantKey moves with the function that makes it. Tests follow the moved and renamed code; the tests of the removed conversions go with them. Model: opus-5-5
This commit was merged in pull request #323.
This commit is contained in:
+33
-35
@@ -16,7 +16,7 @@ import (
|
||||
|
||||
"sneak.berlin/go/pixa/internal/clientip"
|
||||
"sneak.berlin/go/pixa/internal/encurl"
|
||||
"sneak.berlin/go/pixa/internal/imgcache"
|
||||
"sneak.berlin/go/pixa/internal/imagerequest"
|
||||
"sneak.berlin/go/pixa/internal/templates"
|
||||
)
|
||||
|
||||
@@ -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,9 +154,8 @@ func (s *Handlers) HandleGenerateURL() http.HandlerFunc {
|
||||
}
|
||||
|
||||
// The image URL must fetch the source URL as it was written
|
||||
sourceRequest := payload.ToImageRequest()
|
||||
sourceRequest.AllowHTTP = s.config.AllowHTTP
|
||||
fetchURL := sourceRequest.SourceURL()
|
||||
req.AllowHTTP = s.config.AllowHTTP
|
||||
fetchURL := req.SourceURL()
|
||||
|
||||
if !fetchedAsWritten(parsed, fetchURL) {
|
||||
s.renderGeneratorWithForm(w, r, "Source URL cannot be fetched as "+
|
||||
@@ -167,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,
|
||||
@@ -240,14 +239,15 @@ func fetchedAsWritten(source *url.URL, fetchURL string) bool {
|
||||
fetched.RawQuery == source.RawQuery
|
||||
}
|
||||
|
||||
// buildGeneratePayload parses the numeric form fields and assembles the
|
||||
// encrypted URL payload. ttl=0 means never expires (ExpiresAt stays 0). 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(
|
||||
// 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 buildGenerateRequest(
|
||||
parsed *url.URL, form url.Values,
|
||||
) (*encurl.Payload, time.Time, int, error) {
|
||||
) (*imagerequest.Request, time.Time, int, error) {
|
||||
width, err := parseFormDimension(form, "width")
|
||||
if err != nil {
|
||||
return nil, time.Time{}, 0, err
|
||||
@@ -269,42 +269,40 @@ func buildGeneratePayload(
|
||||
return nil, time.Time{}, 0, err
|
||||
}
|
||||
|
||||
fitMode := imgcache.FitMode(form.Get("fit"))
|
||||
fitMode := imagerequest.Fit(form.Get("fit"))
|
||||
|
||||
err = imgcache.ValidateFitMode(fitMode)
|
||||
err = imagerequest.ValidateFitMode(fitMode)
|
||||
if err != nil {
|
||||
return nil, time.Time{}, 0,
|
||||
fmt.Errorf("%w: %s", imgcache.ErrInvalidFitMode, form.Get("fit"))
|
||||
fmt.Errorf("%w: %s", imagerequest.ErrInvalidFitMode, form.Get("fit"))
|
||||
}
|
||||
|
||||
var (
|
||||
expiresAt time.Time
|
||||
expiresAtUnix int64
|
||||
)
|
||||
|
||||
var expiresAt time.Time
|
||||
if ttl > 0 {
|
||||
expiresAt = time.Now().Add(time.Duration(ttl) * time.Second)
|
||||
expiresAtUnix = expiresAt.Unix()
|
||||
}
|
||||
|
||||
payload := &encurl.Payload{
|
||||
SourceHost: parsed.Host,
|
||||
SourcePath: parsed.Path,
|
||||
SourceQuery: parsed.RawQuery,
|
||||
Width: width,
|
||||
Height: height,
|
||||
Format: imgcache.ImageFormat(form.Get("format")),
|
||||
Quality: quality,
|
||||
FitMode: fitMode,
|
||||
ExpiresAt: expiresAtUnix,
|
||||
req := &imagerequest.Request{
|
||||
Source: imagerequest.Source{
|
||||
Host: parsed.Host,
|
||||
Path: parsed.Path,
|
||||
Query: parsed.RawQuery,
|
||||
},
|
||||
Transform: imagerequest.Transform{
|
||||
Size: imagerequest.Size{Width: width, Height: height},
|
||||
Format: imagerequest.Format(form.Get("format")),
|
||||
Quality: quality,
|
||||
FitMode: fitMode,
|
||||
},
|
||||
Expires: expiresAt,
|
||||
}
|
||||
|
||||
return payload, expiresAt, ttl, nil
|
||||
return req, expiresAt, ttl, nil
|
||||
}
|
||||
|
||||
// parseFormDimension reads an optional width or height form field. An empty
|
||||
// value means "original size" (0). A non-numeric value, or one
|
||||
// imgcache.ValidateDimension rejects, is an error naming the field.
|
||||
// imagerequest.ValidateDimension rejects, is an error naming the field.
|
||||
func parseFormDimension(form url.Values, field string) (int, error) {
|
||||
raw := form.Get(field)
|
||||
if raw == "" {
|
||||
@@ -316,7 +314,7 @@ func parseFormDimension(form url.Values, field string) (int, error) {
|
||||
return 0, fmt.Errorf("%w %s: not a number", errInvalidFormField, field)
|
||||
}
|
||||
|
||||
err = imgcache.ValidateDimension(field, value)
|
||||
err = imagerequest.ValidateDimension(field, value)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user