[PR #887] fix(shims): skip body copy for GET/HEAD in NextRequest constructor #919

Open
opened 2026-05-06 13:10:50 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/887
Author: @agm151515
Created: 4/24/2026
Status: 🔄 Open

Base: mainHead: fix/nextrequest-skip-body-for-get-head


📝 Commits (1)

  • dc04a22 fix(shims): skip body copy for GET/HEAD in NextRequest constructor

📊 Changes

2 files changed (+48 additions, -3 deletions)

View changed files

📝 packages/vinext/src/shims/server.ts (+7 -3)
📝 tests/shims.test.ts (+41 -0)

📄 Description

Summary

When NextRequest is constructed from an existing Request, its
constructor forwards body: req.body to super() unconditionally.
The Fetch spec (and workerd) throw
TypeError: Request with a GET or HEAD method cannot have a body.
whenever init.body is non-null and the method is GET/HEAD.

In Cloudflare Workers, incoming GET/HEAD requests expose
request.body as a non-null ReadableStream whenever the request
carries Content-Length or Transfer-Encoding framing. That happens
in the wild — e.g. some email image-proxy fetchers of tracking pixels
send GET with a Content-Length header — so the proxy/middleware
block in the generated RSC entry throws on every affected request,
logs [vinext] Middleware error: TypeError: …, and returns 500.

Reproduced via wrangler dev --local against a minimal worker:

GET / (normal, no framing)         → request.body === null,  NextRequest OK
GET / Content-Length: 5, body=hi   → request.body === stream, NextRequest THREW
HEAD / Transfer-Encoding: chunked  → request.body === stream, NextRequest THREW

Fix gates body/duplex behind a method check. Behavior for
POST/PUT/PATCH/DELETE etc. is unchanged.

Test plan

  • New regression test in tests/shims.test.ts reproduces the bug
    in Node (by overriding body on a normal Request via
    Object.defineProperty) — fails before the fix, passes after.
  • Existing NextRequest tests still pass (pnpm test:unit -t NextRequest → 21 passed).
  • Full unit suite passes (pnpm test:unit → 2971/2971).
  • pnpm fmt:check and pnpm lint clean on modified files.

Downstream context for maintainers: this was observed in production on
scoregap.com with vinext 0.0.43. Filed locally as GitHub issue #35 in
our app repo. Happy to adjust style/commit-msg to match project
conventions.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/887 **Author:** [@agm151515](https://github.com/agm151515) **Created:** 4/24/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/nextrequest-skip-body-for-get-head` --- ### 📝 Commits (1) - [`dc04a22`](https://github.com/cloudflare/vinext/commit/dc04a22ad5fbc0d93b81551def3e7abd4f27d344) fix(shims): skip body copy for GET/HEAD in NextRequest constructor ### 📊 Changes **2 files changed** (+48 additions, -3 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/shims/server.ts` (+7 -3) 📝 `tests/shims.test.ts` (+41 -0) </details> ### 📄 Description ## Summary When `NextRequest` is constructed from an existing `Request`, its constructor forwards `body: req.body` to `super()` unconditionally. The Fetch spec (and workerd) throw `TypeError: Request with a GET or HEAD method cannot have a body.` whenever `init.body` is non-null and the method is `GET`/`HEAD`. In Cloudflare Workers, incoming `GET`/`HEAD` requests expose `request.body` as a **non-null** `ReadableStream` whenever the request carries `Content-Length` or `Transfer-Encoding` framing. That happens in the wild — e.g. some email image-proxy fetchers of tracking pixels send `GET` with a `Content-Length` header — so the proxy/middleware block in the generated RSC entry throws on every affected request, logs `[vinext] Middleware error: TypeError: …`, and returns 500. Reproduced via `wrangler dev --local` against a minimal worker: ``` GET / (normal, no framing) → request.body === null, NextRequest OK GET / Content-Length: 5, body=hi → request.body === stream, NextRequest THREW HEAD / Transfer-Encoding: chunked → request.body === stream, NextRequest THREW ``` Fix gates `body`/`duplex` behind a method check. Behavior for `POST`/`PUT`/`PATCH`/`DELETE` etc. is unchanged. ## Test plan - [x] New regression test in `tests/shims.test.ts` reproduces the bug in Node (by overriding `body` on a normal Request via `Object.defineProperty`) — fails before the fix, passes after. - [x] Existing `NextRequest` tests still pass (`pnpm test:unit -t NextRequest` → 21 passed). - [x] Full unit suite passes (`pnpm test:unit` → 2971/2971). - [x] `pnpm fmt:check` and `pnpm lint` clean on modified files. Downstream context for maintainers: this was observed in production on scoregap.com with vinext 0.0.43. Filed locally as GitHub issue #35 in our app repo. Happy to adjust style/commit-msg to match project conventions. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#919
No description provided.