check / check (push) Canceled after 0s
seal.DeriveKeys derives the session hash and block keys, the encrypted URL key and the CSRF key from the signing key, with their salts declared beside it, and returns them as one seal.Keys. internal/providers calls it once at startup and provides the value to the fx graph. The session manager, the encrypted URL generator and the CSRF protection each take their own key. session.NewManager, encurl.NewGenerator, newCSRFProtect and handlers.New return no error, as nothing in them can fail now. Each key is derived as before, with seal.DeriveKey and the same salt. The signing key itself stays the HMAC key of signed URLs and the login password. README.md says under signing_key what it protects. Model: opus-5-5
99 lines
2.6 KiB
Go
99 lines
2.6 KiB
Go
package server
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"sneak.berlin/go/pixa/internal/encurl"
|
|
"sneak.berlin/go/pixa/internal/imagerequest"
|
|
"sneak.berlin/go/pixa/internal/seal"
|
|
)
|
|
|
|
// TestImageProxyRefusesFitOutsideAboveMaximum requests sizes with fit=outside
|
|
// through both image routes. fit=outside scales the source to cover the size,
|
|
// and so past it on one side: a size for which that side would be above 8192
|
|
// is refused with 400 and the JSON error body, whether it is the width or the
|
|
// height, and a size for which it stays within 8192 is served at the scaled
|
|
// size.
|
|
func TestImageProxyRefusesFitOutsideAboveMaximum(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// The upstream paths of the sources
|
|
const (
|
|
widePath = "/wide.png"
|
|
rowPath = "/row.png"
|
|
columnPath = "/column.png"
|
|
)
|
|
|
|
sources := map[string][]byte{
|
|
widePath: encodeTestPNG(t, 3000, 600),
|
|
rowPath: encodeTestPNG(t, 8192, 1),
|
|
columnPath: encodeTestPNG(t, 1, 8192),
|
|
}
|
|
|
|
upstream := httptest.NewServer(http.HandlerFunc(
|
|
func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "image/png")
|
|
_, _ = w.Write(sources[r.URL.Path])
|
|
}))
|
|
t.Cleanup(upstream.Close)
|
|
|
|
s, _, _ := startImageProxy(t, upstream)
|
|
|
|
keys, err := seal.DeriveKeys(testSigningKey)
|
|
if err != nil {
|
|
t.Fatalf("seal.DeriveKeys: %v", err)
|
|
}
|
|
|
|
generator := encurl.NewGenerator(keys.EncryptedURLKey)
|
|
|
|
tests := []struct {
|
|
path string
|
|
width, height int
|
|
// wantWidth and wantHeight are the served image's, 0 for a refusal
|
|
wantWidth, wantHeight int
|
|
}{
|
|
{widePath, 1, 8192, 0, 0},
|
|
{rowPath, 1, 8192, 0, 0},
|
|
{columnPath, 8192, 1, 0, 0},
|
|
{widePath, 1, 1200, 6000, 1200},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
token, err := generator.Generate(&imagerequest.Request{
|
|
Source: imagerequest.Source{Host: upstreamHost, Path: tt.path},
|
|
Transform: imagerequest.Transform{
|
|
Size: imagerequest.Size{Width: tt.width, Height: tt.height},
|
|
Format: imagerequest.FormatJPEG,
|
|
FitMode: imagerequest.FitOutside,
|
|
},
|
|
}, time.Time{})
|
|
if err != nil {
|
|
t.Fatalf("encurl Generate: %v", err)
|
|
}
|
|
|
|
size := fmt.Sprintf("%dx%d", tt.width, tt.height)
|
|
|
|
for _, target := range []string{
|
|
"/v1/image/" + upstreamHost + tt.path + "/" + size +
|
|
".jpeg?fit=outside",
|
|
"/v1/e/" + token + "/img.jpg",
|
|
} {
|
|
rec := httptest.NewRecorder()
|
|
s.ServeHTTP(rec, httptest.NewRequestWithContext(
|
|
t.Context(), http.MethodGet, target, nil))
|
|
t.Logf("GET %s: %d, Content-Type %s",
|
|
target, rec.Code, rec.Header().Get("Content-Type"))
|
|
|
|
if tt.wantWidth == 0 {
|
|
checkSizeRefused(t, rec)
|
|
} else {
|
|
checkServedSize(t, rec, tt.wantWidth, tt.wantHeight)
|
|
}
|
|
}
|
|
}
|
|
}
|