Skip to content

[miniflare] R2 local public bucket fixes#14323

Open
tahmid-23 wants to merge 8 commits into
cloudflare:mainfrom
tahmid-23:r2-local-public-bucket-fixes
Open

[miniflare] R2 local public bucket fixes#14323
tahmid-23 wants to merge 8 commits into
cloudflare:mainfrom
tahmid-23:r2-local-public-bucket-fixes

Conversation

@tahmid-23

@tahmid-23 tahmid-23 commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

A series of fixes on my initial PR #14119. These fixes mostly aim to have parity with the real public bucket URL. Some of these are somewhat cosmetic.

  • 401 instead of 405 for methods not allowlisted by the CORS policy
  • Improved range handling (this is multiple commits)
  • HEAD honors the Range header
  • Hono already does url decoding, decoding twice is incorrect
  • Cancelling the r2 object stream isn't strictly necessary I believe, but technically better bookkeeping and I think it shuts up some warning

I observed these behaviors against r2.dev. Some of these checks will be needed for correctness in #14280.


  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: bug fix

A picture of a cute animal (not mandatory, but encouraged)


Open in Devin Review

tahmid-23 and others added 4 commits June 12, 2026 11:12
… R2 public endpoint

Write methods get 401 (not 405): r2.dev has no authenticated mode, writes
go through the S3 API or bindings. Failed preconditions return a bare 412
with no object headers, like r2.dev (whose error responses carry
Cloudflare's HTML error pages; locally only the status code is mimicked).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on the local R2 public endpoint

R2's HTTP endpoints only accept a single range with start <= end; anything
else (including multiple ranges) is rejected with 400 rather than ignored.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
r2.dev answers ranged HEAD requests with a bodyless 206 and Content-Range;
previously the range was ignored for HEAD and a 200 with the full length
was returned.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…c endpoint

`object.range` may carry all keys with some undefined (e.g. `suffix`
present but undefined on an offset range), so normalize by value rather
than key presence. Suffix ranges (`bytes=-N`) previously fell through to
a 200 whose Content-Length reported the full object size against a
partial body.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 16, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 72537be

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
miniflare Patch
@cloudflare/deploy-helpers Patch
@cloudflare/pages-shared Patch
@cloudflare/vite-plugin Patch
@cloudflare/vitest-pool-workers Patch
wrangler Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-project-automation github-project-automation Bot moved this to Untriaged in workers-sdk Jun 16, 2026
@workers-devprod workers-devprod requested review from a team and emily-shen and removed request for a team June 16, 2026 11:43
@workers-devprod

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • @cloudflare/wrangler
Show detailed file reviewers
  • .changeset/r2-local-public-fixes.md: [@cloudflare/wrangler]
  • packages/miniflare/src/workers/r2/public.worker.ts: [@cloudflare/wrangler]
  • packages/miniflare/test/plugins/r2/public.spec.ts: [@cloudflare/wrangler]

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

Open in Devin Review

Comment thread packages/miniflare/src/workers/r2/public.worker.ts
}
if (!("body" in recheck)) {
return c.body(null, { status: 412, headers: objectHeaders(recheck) });
return c.body(null, 412);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 412 response no longer includes object headers — intentional behavioral change

The old code at this line returned c.body(null, { status: 412, headers: objectHeaders(recheck) }), including ETag, Last-Modified, etc. in the 412 response. The new code returns c.body(null, 412) with no headers at all. Per RFC 7232 §4.2, a 412 response SHOULD include entity headers. The PR intends to match r2.dev behavior, and the tests only assert the status code, so this appears intentional. Worth confirming this matches actual r2.dev responses if fidelity is important.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@tahmid-23 tahmid-23 force-pushed the r2-local-public-bucket-fixes branch from 37a6395 to de6e279 Compare June 16, 2026 12:06
devin-ai-integration[bot]

This comment was marked as resolved.

@pkg-pr-new

pkg-pr-new Bot commented Jun 16, 2026

Copy link
Copy Markdown
create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@14323

@cloudflare/deploy-helpers

npm i https://pkg.pr.new/@cloudflare/deploy-helpers@14323

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@14323

miniflare

npm i https://pkg.pr.new/miniflare@14323

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@14323

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@14323

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@14323

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@14323

@cloudflare/workers-auth

npm i https://pkg.pr.new/@cloudflare/workers-auth@14323

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@14323

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@14323

wrangler

npm i https://pkg.pr.new/wrangler@14323

commit: 72537be

tahmid-23 and others added 4 commits June 16, 2026 08:25
…ic endpoint

The simulator clamps ranges starting at or beyond the object size; r2.dev
rejects them with 416.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…dpoint

Hono already percent-decodes path params, so decoding them again corrupted
keys containing `%`: a literal `%` that does not form a valid escape threw
a URIError (surfacing as a bare 500), and keys like `a%2Bb` were silently
served as `a+b`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The public endpoint must fetch with `bucket.get()` even for HEAD (only
`get` evaluates conditional headers and ranges), and the 416 path returns
before reading the body. Cancel the stream in both cases instead of
leaving it open until garbage collection.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ation

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tahmid-23 tahmid-23 force-pushed the r2-local-public-bucket-fixes branch from de6e279 to 72537be Compare June 16, 2026 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

2 participants