Skip to content

fix(cloudflare): Forward method, headers and body when a Request is passed as fetch init - #26368

Open
Vivek1898 wants to merge 1 commit into
getsentry:developfrom
Vivek1898:fix/cloudflare-instrument-fetcher-request-init
Open

Vivek1898 wants to merge 1 commit into
getsentry:developfrom
Vivek1898:fix/cloudflare-instrument-fetcher-request-init

Conversation

@Vivek1898

Copy link
Copy Markdown

Fixes #26367

The problem

instrumentFetcher built the outgoing init with an object spread:

const mergedInit = { ...init, ...(headers ? { headers } : {}) };
return fetchFn(input, mergedInit);

Forwarding a request as stub.fetch(url, request) is a common Workers idiom, so init is often itself a Request. A Request's method, headers, body and the rest are prototype getters, not own enumerable properties, so the spread copied none of them. Behind an instrumented Durable Object namespace or service binding the call reached the object as a bare GET with no headers and no body, which broke WebSocket upgrades (Upgrade: websocket) and every forwarded POST. The same call works without Sentry.

The fix

Handle a Request-valued init the same way the existing input instanceof Request && init === undefined branch already handles a Request input: rebuild through the Request constructor, which reads method, headers and body by property access, then layer the tracing headers (which already include the request's own headers) on top. Plain-object init still goes through the existing spread path, so no other case changes.

Tests

Added two cases to instrumentFetcher.test.ts: a Request-valued init with a method, headers and body is forwarded intact with tracing headers added, and the same holds (minus tracing) when trace data is empty.

…assed as fetch init

`instrumentFetcher` built the outgoing init with an object spread (`{ ...init }`).
When `init` is itself a Request (the common `stub.fetch(url, request)` Workers
idiom), its method, headers and body are prototype getters rather than own
properties, so the spread copied none of them. Behind an instrumented Durable
Object or service binding the call arrived as a bare GET with no headers and no
body, breaking WebSocket upgrades and forwarded POSTs that work without Sentry.

Handle a Request-valued `init` the same way the existing single-Request branch
does: rebuild through the Request constructor (which reads those members by
property access) and layer the tracing headers, which already include the
request's own headers, on top.

Fixes getsentry#26367
@Vivek1898
Vivek1898 requested review from a team and JPeer264 November 13, 2026 18:04
@github-actions github-actions Bot added the external PR from an external contributor label Nov 13, 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

external PR from an external contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@sentry/cloudflare 11: instrumented Durable Object stubs drop method, headers and body when init is a Request

1 participant