Skip to content

fix: skip ASSETS binding fetch for non-GET/HEAD requests - #54

Merged
Brooooooklyn merged 2 commits into
mainfrom
fix/skip-assets-fetch-for-non-get
Mar 31, 2026
Merged

Brooooooklyn merged 2 commits into
mainfrom
fix/skip-assets-fetch-for-non-get

Conversation

@Brooooooklyn

@Brooooooklyn Brooooooklyn commented Mar 31, 2026 •

Copy link
Copy Markdown
Member

POST/PUT/PATCH/DELETE requests to unmatched paths (e.g. bot traffic to
/xmlrpc.php) were passed to env.ASSETS.fetch(), which internally
reconstructs the Request in workerd C++. If any middleware had consumed
the request body, this threw "Cannot reconstruct a Request with a used
body" and returned 500.

Static assets are only served via GET/HEAD — the ASSETS worker returns
405 for other methods anyway. Guard all three ASSETS fetch call sites:

  • serveWithAssets: entry-point fallback for non-pages apps
  • fetchPagesAsset: pages-mode asset fallback for extension paths
  • notFound handler: skip page rendering and asset lookup entirely for
    non-GET/HEAD requests to non-API paths

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com


Note

Low Risk
Small, targeted guards around static-asset fallthrough and test harness changes; main risk is unexpected 404 behavior for non-GET/HEAD requests that previously reached ASSETS.fetch().

Overview
Stops routing fallbacks from hitting the ASSETS binding for non-GET/HEAD requests by adding method guards in pages-mode (fetchPagesAsset() and the app.notFound handler) and in the worker entry fallback helper serveWithAssets().

Improves integration test stability by holding ports allocated by getPort() until waitForServer() runs (reducing parallel-test TOCTOU port races) and increases the Node production server startup wait in node-target.test.ts.

Written by Cursor Bugbot for commit 7a9dba8. This will update automatically on new commits. Configure here.

POST/PUT/PATCH/DELETE requests to unmatched paths (e.g. bot traffic to
/xmlrpc.php) were passed to env.ASSETS.fetch(), which internally
reconstructs the Request in workerd C++. If any middleware had consumed
the request body, this threw "Cannot reconstruct a Request with a used
body" and returned 500.

Static assets are only served via GET/HEAD — the ASSETS worker returns
405 for other methods anyway. Guard all three ASSETS fetch call sites:

- serveWithAssets: entry-point fallback for non-pages apps
- fetchPagesAsset: pages-mode asset fallback for extension paths
- notFound handler: skip page rendering and asset lookup entirely for
  non-GET/HEAD requests to non-API paths

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Copy link
Copy Markdown
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 811def6bed

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread test/integration-helpers.ts
…n tests

getPort() found a free port by binding to port 0, then immediately
closed the socket. When ~16 integration tests ran in parallel, another
test's getPort() could grab the same port during the gap between close
and the child process's listen(), causing "address in use" failures.

Hold the socket open until waitForServer() is called (right after
spawn()), so no other test can steal the port. Also bump the
node-target production server timeout from 10s to 20s to match other
integration tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Brooooooklyn
Brooooooklyn force-pushed the fix/skip-assets-fetch-for-non-get branch from 811def6 to 7a9dba8 Compare March 31, 2026 08:43
@Brooooooklyn
Brooooooklyn merged commit 6e8e819 into main Mar 31, 2026
8 checks passed
@Brooooooklyn
Brooooooklyn deleted the fix/skip-assets-fetch-for-non-get branch March 31, 2026 09:00
cpojer pushed a commit that referenced this pull request Sep 11, 2026
…#54)

When all assets are already cached, CF returns empty buckets and the
session JWT is already the completion token. The previous implementation
incorrectly tried to "exchange" the upload token by POSTing to the
upload endpoint with CF_API_TOKEN, which is not how the CF API works.

This commit rewrites uploadAssetBuckets to match Wrangler's
implementation:

- Return session JWT directly when buckets are empty (no exchange needed)
- Use buckets.flat().length === 0 to handle both [] and [[]] from CF
- Add per-bucket retry with exponential backoff (5 attempts)
- Remove apiToken parameter (only used in broken exchange logic)
- Fix Object.keys(assetsByHash) on Map (always returned 0)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

2 participants