You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(node): keep derived content-length when FastResponse materializes - #335
On Node, FastResponse only worked out content-type / content-length for string and byte bodies inside _toNodeResponse(). When anything read .body (or called .clone(), .text(), …) first, the _response getter built a native Response with no content-length, so srvx sent the response chunked. A HEAD response had no length header at all.
_response now sets these headers for string, ArrayBuffer, Uint8Array, DataView and Blob bodies, using the same rules as _toNodeResponse():
content-length is the body's byte length (Buffer.byteLength for strings, .size for Blob).
content-type is srvx's text/plain; charset=UTF-8 for strings, or blob.type, and is only set when the header is missing.
Headers the user set always win. A shared Headers passed as init is copied, never changed.
Stream and Node Readable bodies are unchanged.
Body-wrapping layers like env-runner's RunnerManager (unjs/env-runner#92) can now read .body and keep the framing. They no longer need to call _toNodeResponse() directly.
Tests: added FastResponse keeps derived content-length once materialized in test/node-adapters.test.ts. It covers each body type, user header precedence, headers changed before materializing, not mutating a shared init, and an end-to-end GET and HEAD through serve(). The new tests fail without the fix. The full suite, lint and typecheck pass.
🤖 Generated with AI assistant
Summary by CodeRabbit
Bug Fixes
Responses now include inferred content type and content length for supported body types when those headers aren’t already set.
Materialized responses send the correct body length without unnecessary transfer-encoding, including for HEAD requests.
Existing headers remain unchanged, and streamed responses do not receive an inferred content length.
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: b1f639ba-9863-4711-9b40-c20352325233
📥 Commits
Reviewing files that changed from the base of the PR and between 008a954 and 02c7c6d.
📒 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; 0 remain after this review.
📝 Walkthrough
Node response materialization now derives content type and content length for supported body types when those headers are absent. Regression tests cover header preservation, streams, and HTTP framing for GET and HEAD responses.
Changes: Node response header preservation
Layer / File(s)
Summary
Derive headers during materialization src/adapters/_node/response.ts, test/node-adapters.test.ts
_response derives content type and byte length for strings, buffers, typed arrays, DataView, and Blob bodies. Explicit headers take precedence, mutations made before materialization remain present, shared Headers objects are not mutated, and streams receive no derived length.
h3js/srvx#330 — It changes how NodeResponse resolves NativeResponse, which this change uses during materialization.
h3js/srvx#331 — It changes native Response constructor resolution used by this change’s materialization path.
Merge Risk:⚪ Minimal · up to 02c7c
The reviewed header behavior is consistent across materialized and direct Node responses. No issue identified here needs resolution before merge.
Pre-merge checks: 5
Check name
Status
Explanation
Description Check
Check skipped - CodeRabbit’s high-level summary is enabled.
Title check
The title names the change: keeping derived content-length when FastResponse materializes, scoped to the node adapter. The changeset adds header derivation in NodeResponse._response (content-length, a…
Linked Issues check
Issue #332 requires materialized Node FastResponse objects to retain derived framing headers for string, ArrayBuffer, Uint8Array, DataView, and Blob bodies. The change derives byte length and content …
Out of Scope Changes check
The source change is limited to materialized Node response headers. The added tests directly verify issue #332 behavior. No unrelated production change or unrelated test objective is evidenced.
Docstring Coverage
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…
Full details: Title check
Explanation
The title names the change: keeping derived content-length when FastResponse materializes, scoped to the node adapter. The changeset adds header derivation in NodeResponse._response (content-length, and content-type when absent) and regression tests for materialized responses. The title is specific and matches the main change.
Full details: Linked Issues check
Explanation
Issue #332 requires materialized Node FastResponse objects to retain derived framing headers for string, ArrayBuffer, Uint8Array, DataView, and Blob bodies. The change derives byte length and content type in _response, preserves existing headers, and leaves stream bodies without derived length. The added tests cover body types, header precedence, shared-header isolation, and GET and HEAD framing through serve().
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
📝 Generate docstrings
Commit to this branch
Create a new PR
🧪 Generate unit tests (beta)
Commit to this branch
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.
A rabbit checked the headers in a line, Then watched the byte count fit just fine. Strings and blobs now carry their size, While streams stay free of guessed replies. GET and HEAD keep framing clear, The rabbit hops away with cheer.
Comment @coderabbitai help to get the list of available commands.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #332
On Node,
FastResponseonly worked outcontent-type/content-lengthfor string and byte bodies inside_toNodeResponse(). When anything read.body(or called.clone(),.text(), …) first, the_responsegetter built a nativeResponsewith nocontent-length, so srvx sent the response chunked. A HEAD response had no length header at all._responsenow sets these headers for string,ArrayBuffer,Uint8Array,DataViewandBlobbodies, using the same rules as_toNodeResponse():content-lengthis the body's byte length (Buffer.byteLengthfor strings,.sizefor Blob).content-typeis srvx'stext/plain; charset=UTF-8for strings, orblob.type, and is only set when the header is missing.Headerspassed as init is copied, never changed.Readablebodies are unchanged.Body-wrapping layers like env-runner's
RunnerManager(unjs/env-runner#92) can now read.bodyand keep the framing. They no longer need to call_toNodeResponse()directly.Tests: added
FastResponse keeps derived content-length once materializedintest/node-adapters.test.ts. It covers each body type, user header precedence, headers changed before materializing, not mutating a shared init, and an end-to-end GET and HEAD throughserve(). The new tests fail without the fix. The full suite, lint and typecheck pass.🤖 Generated with AI assistant
Summary by CodeRabbit
HEADrequests.