Skip to content

Leave unsafe-method responses alone and honor If-Range - #71

Merged
hellerve merged 1 commit into
mainfrom
fix/unsafe-methods-if-range
Oct 4, 2026
Merged

hellerve merged 1 commit into
mainfrom
fix/unsafe-methods-if-range

Conversation

@hellerve

@hellerve hellerve commented Oct 3, 2026

Copy link
Copy Markdown
Member

Two correctness fixes. They are the parts of #70 worth keeping.

Conditional requests on state-changing methods. web evaluates If-None-Match after the handler has run. For a PUT, POST, PATCH or DELETE the write has already happened by then, and the response's ETag describes the new representation. A conditional create (PUT with If-None-Match: *) wrote and was then answered with a 412, so the client was told its create failed after it succeeded. web now answers only a GET or HEAD with a 304, and sends any other method's response as the handler built it. A handler that needs a precondition checks it before it acts, with http's Request.preconditions against the resource's current validators. Nothing produces a 412 any more, so web-precondition-failed is removed.

If-Range. It was ignored. A Range request for a static file that had changed got a 206 with bytes of the new file, and a client resuming a download appended them to the old file's bytes. web-mark-range now arms the range only when If-Range is absent or names the current version, through http's Request.if-range-matches?. A weak ETag never matches (RFC 9110 §13.1.5). The check runs only for a static-file response to a request that carries Range, and it reads the response's validators only when If-Range is present.

Tests. test/web.carp is 408/0 and test/websocket.carp is 155/0, both with -Werror. The smoke test and gendocs pass.

  • 15 new tests. On main, the 10 that pin the new behaviour fail, and the 5 that pin unchanged behaviour (a current ETag or Last-Modified in If-Range still gets a 206, If-Range without Range is ignored) pass.
  • Removing the If-Range gate fails 5 tests. Removing the GET/HEAD gate fails 6.
  • The tests of the 412's shape are removed, along with cors-conditional, which only they used.

Cost. I timed main against this branch with 5,000 GETs through web-build-response per run, over five request types (plain, If-None-Match miss and hit, browser revalidation, If-Modified-Since hit), at -O0, -O1, -O2, -O3, -Os and --optimize, with five shuffled rounds. Every difference is within ±1.5% and inside the run-to-run spread of 1–4%, and the status codes are identical.

carp-fmt changes nothing on the lines this touches.

@hellerve
hellerve merged commit 1b010ed into main Oct 4, 2026
2 checks passed
@hellerve
hellerve deleted the fix/unsafe-methods-if-range branch October 4, 2026 07:04
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