Skip to content

fix: negotiate HEAD content type on bucket root - #26

Merged
krokicki merged 1 commit into
mainfrom
fix-head-bucket-root
Jul 30, 2026
Merged

fix: negotiate HEAD content type on bucket root#26
krokicki merged 1 commit into
mainfrom
fix-head-bucket-root

Conversation

@krokicki

@krokicki krokicki commented Jul 29, 2026

Copy link
Copy Markdown
Member

Problem

Follow-up to the item noted as out-of-scope in #25: HEAD /{bucket}/ returns content-type: application/xml unconditionally, while GET /{bucket}/ negotiates on Accept and serves the browse UI (text/html) to browsers. Per RFC 9110 §9.3.2, HEAD should report the same headers GET would have sent.

Fix

In head_object's bucket-root branch, negotiate the content type with the same _prefers_html() helper GET uses, and set Vary: Accept since the response now varies on it (same reasoning as #24/#25 — the nginx proxy cache stores HEAD responses too).

The unbrowseable 403 path is unchanged, matching GET's non-negotiated AccessDenied response.

HEAD /{bucket}/subdir/ is left alone: it maps to HeadObject on the key and 404s (tested behavior in test_head_object), which matches real S3 semantics even though GET serves a listing there.

Testing

Added test_head_bucket_root_index mirroring test_head_root_index: asserts status, negotiated content type, and Vary for both Accept types, and compares HEAD against GET on the same URL. Verified it fails without the app change and passes with it.

Full suite: 73 passed.

@StephanPreibisch @neomorphic

Follow-up to #25: HEAD /{bucket}/ returned application/xml
unconditionally, while GET on the same URL serves the browse UI to
clients that prefer HTML. Reuse _prefers_html so HEAD reports the
content type GET would have sent, and set Vary: Accept since the
response now varies on it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@krokicki
krokicki merged commit 99d9bdf into main Jul 30, 2026
5 checks passed
@krokicki
krokicki deleted the fix-head-bucket-root branch July 30, 2026 12:16
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