From f4792a0b025ca7e1763e7830446a947679b80c02 Mon Sep 17 00:00:00 2001 From: Dominik Schmidt Date: Sat, 17 Oct 2026 10:17:28 +0200 Subject: [PATCH] fix(webdav): keep the acceptance contract for previews An explicit x=0 or y=0 is an error again, only an omitted axis is unconstrained, and the text preview fixtures carry the resolution the generator writes now. --- services/webdav/README.md | 8 ++++---- services/webdav/pkg/dav/requests/thumbnail.go | 14 ++++++-------- .../webdav/pkg/dav/requests/thumbnail_test.go | 3 +-- .../acceptance/fixtures/text-file-fixture.jpg | Bin 68518 -> 68518 bytes tests/acceptance/fixtures/unicode-fixture.jpg | Bin 10023 -> 10023 bytes 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/services/webdav/README.md b/services/webdav/README.md index 6bcdcd6832..a572230bb8 100644 --- a/services/webdav/README.md +++ b/services/webdav/README.md @@ -21,8 +21,8 @@ The following query parameters are supported: | Parameter | Required | Default Value | Description | | --------- | -------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------- | | preview | YES | 1 | generates preview | -| x | NO | 32, when y is absent too | horizontal target size, `0` or absent leaves the width unconstrained | -| y | NO | 32, when x is absent too | vertical target size, `0` or absent leaves the height unconstrained | +| x | NO | 32, when y is absent too | horizontal target size, absent leaves the width unconstrained, `0` is an error | +| y | NO | 32, when x is absent too | vertical target size, absent leaves the height unconstrained, `0` is an error | | scalingup | NO | 0 | accepted for compatibility but ignored; not forwarded to the generator | | a | NO | 1 | aspect ratio (legacy; only honored when no explicit `processor` is given) | | c | NO | Caching string | Clients should send the etag, so they get a fresh thumbnail after a file change | @@ -30,7 +30,7 @@ The following query parameters are supported: #### Thumbnail Resolution -`WEBDAV_THUMBNAIL_RESOLUTIONS` is a ladder of edge lengths, not a list of boxes. Each axis of a request is rounded up to the next length on the ladder, on its own, so a thumbnail never comes back in a different orientation than it was asked for. The largest length is the cap: a request above it, and an axis left unconstrained with `0`, get that one. +`WEBDAV_THUMBNAIL_RESOLUTIONS` is a ladder of edge lengths, not a list of boxes. Each axis of a request is rounded up to the next length on the ladder, on its own, so a thumbnail never comes back in a different orientation than it was asked for. The largest length is the cap: a request above it, and an axis left unconstrained, get that one. Example with the default ladder (16, 32, 64, 128, 192, 256, 320, 384, 448, 512, 640, 768, 1024, 1280, 1920, 2560, 3840, 7680): @@ -56,7 +56,7 @@ The following are **legacy aliases** kept for compatibility. They map onto the p To apply one of those, a query parameter has to be added to the request, like `?processor=fit-in`. -Without a processor three things decide, in this order. An unconstrained axis is always fitted, because there is no box to crop to, so `?x=0&y=512` needs nothing else. Then `a` decides when the client sent it: `a=1` fits in, `a=0` fills. Otherwise the source type decides, `resize` for gifs and `fill` for everything else, which is what a request without `a` has always got. +Without a processor three things decide, in this order. An unconstrained axis is always fitted, because there is no box to crop to, so `?y=512` needs nothing else. Then `a` decides when the client sent it: `a=1` fits in, `a=0` fills. Otherwise the source type decides, `resize` for gifs and `fill` for everything else, which is what a request without `a` has always got. When what a request resolves to contradicts an `a` the client sent, the response carries the header `X-OpenCloud-Thumbnail-Aspect-Ignored` so developers can fix their client. A request that does not send `a` never gets the header. diff --git a/services/webdav/pkg/dav/requests/thumbnail.go b/services/webdav/pkg/dav/requests/thumbnail.go index 603c14ff17..f7f7df876c 100644 --- a/services/webdav/pkg/dav/requests/thumbnail.go +++ b/services/webdav/pkg/dav/requests/thumbnail.go @@ -98,9 +98,6 @@ func ParseThumbnailRequest(r *http.Request) (*ThumbnailRequest, error) { if err != nil { return nil, err } - if width == 0 && height == 0 { - return nil, fmt.Errorf("Cannot leave both width and height unconstrained!") - } processor := q.Get("processor") if (width == 0 || height == 0) && processor != "" && cropsToBox(processor) { // A processor that was asked for by name and crops has no target for an @@ -136,10 +133,11 @@ func addMissingStorageID(id string) string { return storagespace.FormatResourceID(rid) } -// parseDimensions reads the requested box. Zero means "do not constrain this -// axis", and an omitted axis is the same as zero, so a client that knows only -// one side can ask for it alone. Only when both are absent does the legacy -// default apply, which keeps the dimensionless OC10 call working. +// parseDimensions reads the requested box. An omitted axis is left +// unconstrained, so a client that knows only one side can ask for it alone, +// while an explicit zero stays the error it has always been. Only when both are +// absent does the legacy default apply, which keeps the dimensionless OC10 call +// working. func parseDimensions(q url.Values) (int64, int64, error) { x, y := q.Get("x"), q.Get("y") if x == "" && y == "" { @@ -161,7 +159,7 @@ func parseDimension(d, name string) (int64, error) { return 0, nil } result, err := strconv.ParseInt(d, 10, 32) - if err != nil || result < 0 { + if err != nil || result <= 0 { // The error message doesn't fit but for OC10 API compatibility reasons we have to set this. return 0, fmt.Errorf("Cannot set %s of 0 or smaller!", name) } diff --git a/services/webdav/pkg/dav/requests/thumbnail_test.go b/services/webdav/pkg/dav/requests/thumbnail_test.go index efe4085017..7ae31726db 100644 --- a/services/webdav/pkg/dav/requests/thumbnail_test.go +++ b/services/webdav/pkg/dav/requests/thumbnail_test.go @@ -75,10 +75,9 @@ func TestParseThumbnailRequestDimensions(t *testing.T) { {name: "both given", query: "x=448&y=448", wantW: 448, wantH: 448}, {name: "neither given keeps the legacy default", query: "preview=1", wantW: DefaultWidth, wantH: DefaultHeight}, {name: "an omitted axis is unconstrained", query: "y=512&processor=fit", wantW: 0, wantH: 512}, - {name: "an explicit zero is unconstrained", query: "x=0&y=512&processor=fit", wantW: 0, wantH: 512}, + {name: "an explicit zero is rejected", query: "x=0&y=512&processor=fit", wantErr: true}, {name: "negative is rejected", query: "x=-1&y=512", wantErr: true}, {name: "an unconstrained axis without a processor is fitted, not rejected", query: "y=512", wantW: 0, wantH: 512}, - {name: "both axes unconstrained is rejected", query: "x=0&y=0&processor=fit", wantErr: true}, {name: "cropping to an unconstrained axis is rejected explicitly", query: "y=512&processor=thumbnail", wantErr: true}, } diff --git a/tests/acceptance/fixtures/text-file-fixture.jpg b/tests/acceptance/fixtures/text-file-fixture.jpg index bfe5711b46bc0ad09c6da50e0d3faafbb52c1aef..59b64a93d64ce09750910e20a8e11c601b74ed7e 100644 GIT binary patch delta 27 hcmZ2Bon_f{mI+DR`jU(cFPIq^fOKQ-)?7wQZUA$L2T}k4 delta 27 hcmZ2Bon_f{mI+DR7Rd|@FPIq^fOKQ-)?7wQZUB4m2lfB} diff --git a/tests/acceptance/fixtures/unicode-fixture.jpg b/tests/acceptance/fixtures/unicode-fixture.jpg index dbf595e8c3bfe95858ab41547f9f4113f51ec9fa..edbc6770c76cf20ed9f00b8572734799aa8bf56b 100644 GIT binary patch delta 22 ccmZ4Px7=?+61To2Bf|@31_mI#F?W|508YsUV*mgE delta 22 ccmZ4Px7=?+61PP%1H%hu1_mI#F?W|5098c?2LJ#7