fix: preserve multiple set-cookie headers in mounted handlers

This commit is contained in:
Cristoper Anderson
2026-02-10 14:40:37 +07:00
parent a82242f042
commit 31e9b5b1af
2 changed files with 38 additions and 7 deletions
+3 -7
View File
@@ -2,8 +2,8 @@ import { serializeCookie } from '../cookies'
import { hasHeaderShorthand, isNotEmpty, StatusMap } from '../utils'
import type { Context } from '../context'
import { isBun } from '../universal/utils'
import { env } from '../universal'
import { isBun } from '../universal/utils'
export const handleFile = (
response: File | Blob,
@@ -343,12 +343,8 @@ export function mergeHeaders(
responseHeaders: Headers,
setHeaders: Context['set']['headers']
) {
const headers = new Headers(
hasHeaderShorthand
? // @ts-ignore
responseHeaders.toJSON()
: Object.fromEntries(responseHeaders.entries())
)
// Direct clone preserves all headers including multiple set-cookie
const headers = new Headers(responseHeaders)
// Merge headers: Response headers take precedence, set.headers fill in non-conflicting ones
if (setHeaders instanceof Headers)
+35
View File
@@ -193,4 +193,39 @@ describe('Mount', () => {
message: 'hello world'
})
})
it('preserve set-cookie headers from Response with CORS', async () => {
const handler = async () => {
const headers = new Headers()
headers.set('location', '/redirect')
headers.append('set-cookie', 'session=abc123; Path=/; HttpOnly')
headers.append('set-cookie', 'token=xyz789; Path=/; Secure')
return new Response('OK', {
status: 302,
headers
})
}
const app = new Elysia()
.use((app) =>
app.onBeforeHandle(({ set }) => {
set.headers['access-control-allow-origin'] = '*'
})
)
.mount('/auth', handler)
const response = await app.handle(
new Request('http://localhost/auth/login', {
method: 'POST'
})
)
const cookies = response.headers.getSetCookie()
expect(cookies).toHaveLength(2)
expect(cookies).toContain('session=abc123; Path=/; HttpOnly')
expect(cookies).toContain('token=xyz789; Path=/; Secure')
expect(response.status).toBe(302)
expect(response.headers.get('location')).toBe('/redirect')
})
})