Skip to content

Fix S3 gateway ignoring If-Match on GetObject and HeadObject - #10604

Open
vshalpnjabi wants to merge 1 commit into
treeverse:masterfrom
vshalpnjabi:fix-s3-getobject-if-match-10581
Open

vshalpnjabi wants to merge 1 commit into
treeverse:masterfrom
vshalpnjabi:fix-s3-getobject-if-match-10581

Conversation

@vshalpnjabi

Copy link
Copy Markdown

Closes #10581

Change Description

Bug Fix

  1. Problem: The S3 gateway's GetObject and HeadObject ignored If-Match, so a read with a stale ETag returned the newer object instead of 412. Clients that pin later parts of a ranged download with If-Match (aws-c-s3 / the CRT client) can end up stitching two versions together.
  2. Root cause: The gateway handlers never evaluated conditional request headers.
  3. Solution: After the object is resolved, GET and HEAD now evaluate If-Match, If-None-Match, If-Unmodified-Since and If-Modified-Since in S3 / RFC 7232 order. The check runs before Range parsing and before the presigned-redirect branch, so a ranged or presigned GET with a stale If-Match returns 412 rather than 206 or 307. Placement follows @RyanLin5967's notes on the issue.

Testing Details

New gateway tests failed before the fix and pass after:

Case Before After
GET, stale If-Match 200 (new body) 412
HEAD, stale If-Match 200 412
Ranged GET, stale If-Match 206 412
Presigned GET, stale If-Match 500 (hit redirect path) 412
Presigned ranged GET, stale If-Match 500 412
GET, matching If-Match 200 200

If-None-Match, If-Modified-Since and If-Unmodified-Since cases also returned 200 before and return 304/412 after. Also ran go build ./cmd/lakefs, go test ./pkg/gateway/... ./pkg/httputil/, gofmt and golangci-lint (0 issues).

Breaking Change?

No, unless a client relied on these headers being ignored. Requests without conditional headers behave as before.

Additional info

This change was AI-assisted using Cursor and was reviewed and tested by me.

GetObject and HeadObject ignored If-Match, so a read with a stale ETag
returned the newer object instead of 412 Precondition Failed. That
breaks ranged downloads that pin parts with If-Match (aws-c-s3).

Evaluate If-Match, If-None-Match, If-Unmodified-Since and
If-Modified-Since after the object is resolved and before Range parsing
or the presigned-redirect branch.
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions github-actions Bot added area/gateway Changes to the gateway area/testing Improvements or additions to tests labels Nov 10, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/gateway Changes to the gateway area/testing Improvements or additions to tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: S3 gateway GetObject ignores If-Match, so a read with a stale ETag returns the newer object

3 participants