Skip to content

fix(node): don't expose derived content-length on FastResponse headers - #337

Open
danielroe wants to merge 1 commit into
h3js:mainfrom
danielroe:fix/content-length
Open

danielroe wants to merge 1 commit into
h3js:mainfrom
danielroe:fix/content-length

Conversation

@danielroe

@danielroe danielroe commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

spotted this in nuxt/nuxt#36671, since nitrojs/nitro#4910 made FastResponse the global Response for Node builds.

since srvx v1.0.7 and #335, reading the body of a Node FastResponse adds a derived content-length to .headers. native Response doesn't do this (and neither did v1.0.6), so "read, transform, rebuild with the original headers" now sends the wrong length and the client sees a truncated body:

const res = new FastResponse('<html>abc</html>', { headers: { 'content-type': 'text/html' } })
const html = await res.text()
res.headers.get('content-length') // '16' (native: null)

const rebuilt = new FastResponse(html + '<!-- overlay -->', { headers: res.headers })
rebuilt.headers.get('content-length') // '16', body is 32 bytes

this PR stores the derived length privately instead and only adds it in _toNodeResponse()...

Summary by CodeRabbit

  • Bug Fixes
    • Improved response body length handling when sending responses, including after the body has been accessed. GET and HEAD responses now preserve appropriate message framing across supported body types.
    • Fully consumed response bodies are sent without a derived content-length value.
    • Response headers now remain consistent with native responses after body-reading operations, and rebuilt responses derive their own content length.

@danielroe
danielroe requested a review from pi0 as a code owner October 24, 2026 16:08
@vercel

vercel Bot commented Oct 24, 2026

Copy link
Copy Markdown

@danielroe is attempting to deploy a commit to the unjs Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 111b3484-e9e6-414d-9dee-5ba3b447600d
Commits

Reviewing files that changed from the base of the PR and between a9a0754 and bfa4002.

Files selected for processing: 2
  • src/adapters/_node/response.ts
  • test/node-adapters.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.

Walkthrough

NodeResponse now stores derived body length separately from native Response headers. Node response conversion applies that length only when the native response body is unused. Tests cover body framing, body consumption, and header comparisons.

Changes: Node response body-length handling

Layer / File(s) Summary
Track and apply derived body length
src/adapters/_node/response.ts
NodeResponse stores the derived body length during native Response materialization. _toNodeResponse() applies it only when the body is unused and clears it during cleanup.
Verify framing and header behavior
test/node-adapters.test.ts
Server tests cover framing for multiple body types, consumed bodies, header comparisons with native Response, and a response rebuilt from read headers.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Possibly related PRs

  • h3js/srvx#335: This PR changes the derived-header behavior introduced by that PR.
Merge Risk: Minimal · up to bfa40

The changed response handling appears ready to merge after normal checks. No unresolved issue is established.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Title check Passed The title clearly and concisely describes the main change: preventing the derived content-length from appearing in FastResponse headers.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2 files.

Finishing Touches: 💡 1
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit checks the length in flight,
And keeps the native headers right.
If body bytes have gone away,
No derived length will join the stay.
Then hops along to test the frame.

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Oct 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@pkg-pr-new

pkg-pr-new Bot commented Oct 24, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/srvx@337

commit: bfa4002

@danielroe danielroe changed the title fix(node): don't expose derived content-length on FastResponse` headers fix(node): don't expose derived content-length on FastResponse headers Oct 24, 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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant