Refuse an unparseable exp with 400; log swallowed cache errors (closes #72)
check / check (push) Successful in 12s
check / check (push) Successful in 12s
An exp that was not a whole number, or empty, was ignored, so a URL for a host that needs a signature got 401 as if it had no exp. It is now a 400 naming exp and the value, on every host; only an exp missing from the URL is unchanged. A failed variant .meta write, source metadata JSON write, Stats count query, stats counter update, negative cache write or expired negative cache delete was discarded without a trace. Each is now logged at warn with the path or key and the error, and stays non-fatal, with tests for those that can be made to fail. VariantStorage takes the cache's logger. Model: opus-5-5
This commit was merged in pull request #141.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -118,3 +119,53 @@ func TestHandleImage_GeneratedSignedURLVerifies(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestHandleImage_InvalidExp_Returns400 sends a signed-host URL whose exp is
|
||||
// not a whole number, and one whose exp is empty. Each is refused with 400
|
||||
// naming exp and the value, not with the 401 a URL without exp still gets.
|
||||
func TestHandleImage_InvalidExp_Returns400(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
query string
|
||||
wantStatus int
|
||||
wantError string
|
||||
}{
|
||||
{"sig=x&exp=banana", http.StatusBadRequest,
|
||||
`invalid exp: not a number, got "banana"`},
|
||||
{"sig=x&exp=", http.StatusBadRequest, `invalid exp: not a number, got ""`},
|
||||
{"sig=x", http.StatusUnauthorized, "unauthorized"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.query, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fix := setupTestHandler(t)
|
||||
|
||||
r := chi.NewRouter()
|
||||
r.Get("/v1/image/*", fix.handler.HandleImage())
|
||||
|
||||
req := httptest.NewRequestWithContext(t.Context(), http.MethodGet,
|
||||
"/v1/image/"+signedHost+"/images/photo.jpg/50x50.jpeg?"+tt.query, nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
r.ServeHTTP(rec, req)
|
||||
t.Logf("GET %s: %d %s", req.URL, rec.Code, rec.Body)
|
||||
|
||||
var body struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
err := json.NewDecoder(rec.Body).Decode(&body)
|
||||
if err != nil {
|
||||
t.Fatalf("decoding response body: %v", err)
|
||||
}
|
||||
|
||||
if rec.Code != tt.wantStatus || body.Error != tt.wantError {
|
||||
t.Errorf("got %d %q, want %d %q",
|
||||
rec.Code, body.Error, tt.wantStatus, tt.wantError)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user