Skip to content

fix: route V1 ListObjects to the list handler instead of raw-forwarding#93

Merged
ServerSideHannes merged 1 commit into
mainfrom
fix/route-v1-list-to-handler
Jun 30, 2026
Merged

fix: route V1 ListObjects to the list handler instead of raw-forwarding#93
ServerSideHannes merged 1 commit into
mainfrom
fix/route-v1-list-to-handler

Conversation

@ServerSideHannes

Copy link
Copy Markdown
Owner

Problem

Even after #92 (serve V1 ListObjects via the backend's V2 API), Scylla backups and Postgres retention still got HTTP 400 from Hetzner. Reason: the request never reached the fixed handler.

_dispatch_bucket raw-forwards any bucket GET whose query lacks list-type/delete/uploads/location:

skip_queries = (QUERY_LIST_TYPE, QUERY_DELETE, QUERY_UPLOADS, QUERY_LOCATION)
if query and not any(q in query for q in skip_queries):
    return await self.handler.forward_request(request, creds)   # raw passthrough

A V1 ListObjects is GET /bucket?prefix&delimiter&max-keys&encoding-type with no list-type=2 → it matched this catch-all and was forwarded verbatim to the backend as V1 → Hetzner 400. handle_list_objects_v1 was only reached for a bare GET /bucket (empty query), so #92's translation never applied to what rclone / barman actually send.

Confirmed on 2026.6.9: backend request logged as GET https://hel1.your-objectstorage.com/…-scylladb-backups-v3?delimiter=%2F&encoding-type=url&max-keys=1000&prefix=… → HTTP/2 400 (no list-type=2 → still V1).

Fix

Treat a bucket GET whose query is only listing params (prefix, delimiter, marker, max-keys, encoding-type, fetch-owner, start-after, continuation-token, list-type) as a listing → fall through to the list handler (which serves V1 via the backend's V2 API). Genuine sub-resource GETs (acl, versioning, cors, location, …) still raw-forward unchanged.

Test

tests/unit/test_dispatch_v1_list.py: V1-with-params and bare GET /bucket route to handle_list_objects_v1; list-type=2 → V2 handler; ?acl/?versioning still forward; ?location → bucket-location. Pre-fix the V1-with-params case routes to forward (asserted). Full unit suite green (546 passed); ruff check + format clean.

Completes the chain: #91 (V2 token) → #92 (V1→V2 in handler) → this (route V1 to the handler).

_dispatch_bucket raw-forwarded any bucket GET whose query lacked
list-type/delete/uploads/location to the backend. A V1 ListObjects
(GET /bucket?prefix&delimiter&max-keys&encoding-type, no list-type=2)
matched that catch-all, so it was sent verbatim to the backend as V1 —
which Hetzner rejects with HTTP 400. handle_list_objects_v1 (which now
serves V1 via the backend's V2 API, #92) was only ever reached for a
bare 'GET /bucket' with no query, so the fix didn't apply to the
requests scylla-manager's rclone and barman-cloud-backup-delete actually
send.

Treat a GET whose query is only listing params (prefix, delimiter,
marker, max-keys, encoding-type, fetch-owner, start-after,
continuation-token, list-type) as a listing and fall through to the list
handler; still raw-forward genuine sub-resource GETs (acl, versioning,
cors, ...).
@ServerSideHannes ServerSideHannes merged commit 0cddafc into main Jun 30, 2026
4 checks passed
@ServerSideHannes ServerSideHannes deleted the fix/route-v1-list-to-handler branch June 30, 2026 10:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant