-
-
Notifications
You must be signed in to change notification settings - Fork 387
🔧 Fix Set-Cookie headers not sent when errors are thrown #1549
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
🔧 Fix Set-Cookie headers not sent when errors are thrown #1549
Conversation
WalkthroughDelegates error response construction to mapResponse by mutating the response Changes
Sequence Diagram(s)sequenceDiagram
participant H as Route Handler
participant C as Error Catch
participant M as mapResponse
participant Client as Client
rect rgba(255,120,120,0.15)
Note over H,Client: OLD — built Response directly (problem: Set-Cookie lost)
H->>H: set.cookie.foo = "v"
H->>H: throw Error()
C->>C: Construct new Response(JSON, headers, status)
C->>Client: Response (Set-Cookie may be missing)
end
rect rgba(120,220,140,0.12)
Note over H,Client: NEW — mutate set and use mapResponse (preserves cookies)
H->>H: set.cookie.foo = "v"
H->>H: throw Error()
C->>C: set.headers['content-type']='application/json'
C->>C: set.status = error.status ?? set.status ?? 500
C->>M: mapResponse(error.message, set)
M->>Client: Response (includes Set-Cookie & headers)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ 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 |
commit: |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/adapter/web-standard/index.ts(1 hunks)src/dynamic-handle.ts(17 hunks)test/core/handle-error.test.ts(1 hunks)
🔇 Additional comments (4)
src/dynamic-handle.ts (2)
6-6: LGTM: Type-only import correctly applied.The change to import
ElysiaErrorsas a type-only import is appropriate since it's used exclusively for type annotations. This improves tree-shaking and clarifies thatElysiaErrorshas no runtime presence, while preserving runtime imports forNotFoundError,status, andValidationError.
728-732: Excellent fix: Error responses now preserve cookies and headers.The change to use
mapResponse(error message, context.set)instead of constructing a Response object directly ensures that cookies and headers set viacontext.setare properly serialized into error responses. This correctly addresses the root cause described in issue #1547.test/core/handle-error.test.ts (1)
553-658: Excellent test coverage for cookie preservation in error scenarios.The nine new test cases provide comprehensive coverage of the fix:
- Various error types (generic Error, ValidationError, NotFoundError, InternalServerError)
- Different error sources (handler throws, validation failure, onError hook)
- Both runtime and AOT modes
- Edge cases (multiple cookies, cookies + custom headers)
All tests are well-structured with clear assertions verifying both the error status codes and the presence of set-cookie headers.
src/adapter/web-standard/index.ts (1)
154-158: LGTM: AOT error handling now preserves cookies and headers.The changes correctly update error response handling for AOT-compiled code:
- Validation errors: Sets content-type and delegates to
mapResponse- Unknown errors: Sets status with proper fallback chain and delegates to
mapResponseBy mutating
set.headersandset.statusbefore callingmapResponse, the AOT adapter now preserves cookies and headers in error responses, consistent with the dynamic handler fix. This ensures the fix works in both runtime and AOT modes.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
7b088f7 to
095bb1d
Compare
This resolves #1547
Problem
Set-Cookie headers are not sent to clients when errors are thrown in route handlers, breaking critical use cases like session rotation on error.
Current Behavior
Before:
This affects:
User Impact
When rotating session cookies on errors (e.g., after detecting suspicious activity), the new session ID is never sent to the client. This leaves the user's session in an invalid state, effectively logging them out unexpectedly.
Root Cause
Error responses were being created directly via
new Response()without callingmapResponse(), which is responsible for serializing cookies fromcontext.set.cookieintoSet-Cookieheaders viahandleSet().This happened in two places:
Dynamic error handler (
src/dynamic-handle.ts:728-734)context.set.cookiewere never serializedAOT compiled error handler (
src/adapter/web-standard/index.ts:153-168)validationErrorandunknownErrorhandlers created Response directlySolution
Changed all error response paths to use
mapResponse()instead of creating Response objects directly. This ensureshandleSet()is called to serialize cookies before the response is created.Changes
1. src/dynamic-handle.ts (lines 728-732)
2. src/adapter/web-standard/index.ts (lines 153-158)
Design Decision
Using
mapResponse()has the added benefit of preserving all headers set viacontext.set.headers, not just cookies. This means CORS headers, custom authentication headers, and other metadata set before an error occurs are also preserved in the error response.Testing
Added 9 comprehensive test cases covering:
Example
After the fix:
After:
session=new-session-id; Path=/✓abc123✓Breaking Changes
None. This fixes behavior that was clearly broken - cookies and headers set before errors should be preserved in error responses.
Summary by CodeRabbit