fix(start-server-core): keep response context headers on non-2xx responses - #7936
fix(start-server-core): keep response context headers on non-2xx responses#7936kdelay wants to merge 3 commits into
Conversation
…onses h3 merges the response context headers into the final response only when `Response.ok` is true, so `mergeEventResponseHeaders` has to do it for the rest. It only restored `set-cookie`, which dropped every other header set through `getResponseHeaders()`/`setResponseHeader()` whenever a server function serialized a non-2xx response. Merge the remaining event headers with the same precedence h3 uses for 2xx responses: `set-cookie` is appended, anything else overrides the header of the response. Responses with immutable headers are rebuilt instead of mutated, which previously threw once the event carried a cookie. Fixes TanStack#7914
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe response pipeline merges response-context headers into responses with any status, preserves multiple ChangesResponse Header Preservation
Estimated code review effort: 3 (Moderate) | ~20 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/start-server-core/tests/request-response.test.ts (1)
54-63: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winAdd coverage for immutable responses with pre-existing cookies.
The immutable-response test only checks a plain header (
x-custom-header). It does not verify that aset-cookieheader already present on an immutable response survives the rebuild inmergeEventResponseHeadersalongside an event-set cookie. Since cookie preservation combined with header rebuilding is a core objective of this PR, add a test that combines both.it('preserves an existing set-cookie header when rebuilding an immutable response', async () => { const response = await run(() => { setCookie('from-event', 'a') const redirect = Response.redirect('http://localhost/next', 302) redirect.headers.append('set-cookie', 'from-response=b') return redirect }) expect(response.headers.getSetCookie()).toEqual([ 'from-response=b', 'from-event=a; Path=/', ]) })🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/start-server-core/tests/request-response.test.ts` around lines 54 - 63, Add coverage alongside the immutable-response test using run, setCookie, and Response.redirect: create an event cookie, append a pre-existing set-cookie header to the immutable redirect, and verify the rebuilt response preserves both cookies in the expected order via getSetCookie.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/start-server-core/src/request-response.ts`:
- Around line 81-116: Update applyEventHeaders to skip content-length alongside
set-cookie when copying eventHeaders, while continuing to append set-cookie
values and preserve all other header merging behavior.
---
Nitpick comments:
In `@packages/start-server-core/tests/request-response.test.ts`:
- Around line 54-63: Add coverage alongside the immutable-response test using
run, setCookie, and Response.redirect: create an event cookie, append a
pre-existing set-cookie header to the immutable redirect, and verify the rebuilt
response preserves both cookies in the expected order via getSetCookie.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: add351aa-662c-4d0b-b0bd-8303e8999556
📒 Files selected for processing (2)
packages/start-server-core/src/request-response.tspackages/start-server-core/tests/request-response.test.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/start-server-core/tests/request-response.test.ts`:
- Around line 76-78: Update the test server setup around server.listen in
beforeAll to wrap the bind in a Promise that rejects on the server's error event
and resolves on successful listening. Attach the error listener before invoking
server.listen so binding failures propagate to beforeAll instead of leaving the
Promise pending.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 14c15da5-0bdd-4ab7-bdf6-19bb7a710f25
📒 Files selected for processing (1)
packages/start-server-core/tests/request-response.test.ts
Fixes #7914
A server function that sets a header through the response context and then serializes a non-2xx response loses that header. Only
set-cookiesurvived, sogetResponseHeaders().set('x-custom-header', 'true')next tosetResponseStatus(401)reached the client as a bare 401.Cause
h3 merges the response context headers into the final response only when
Response.okis true (prepareResponsereturns early on!val.ok).mergeEventResponseHeadersinpackages/start-server-core/src/request-response.tscovers the remaining cases, but it only restoredset-cookieand returned early when the event carried no cookie.Change
mergeEventResponseHeadersnow merges every event header, using the same precedence h3 applies to 2xx responses:set-cookieis appended, anything else overrides the header already on the response. A response whose headers are immutable (Response.redirect, a passed-throughfetchresponse) is rebuilt instead of mutated; that path previously threw as soon as the event carried a cookie.Verification
Added
packages/start-server-core/tests/request-response.test.ts, drivingrequestHandlerdirectly. Three of the five cases fail onmainand pass with this change; the other two pin the existing 2xx and set-cookie behaviour.Both are green.
Summary by CodeRabbit
Bug Fixes
Set-Cookievalues are retained during response processing, including cookies from upstream responses.Tests