Skip to content

Commit

Permalink
fix(context): Retain all cookies when passing ResponseInit to `c.bo…
Browse files Browse the repository at this point in the history
…dy` (#2690)

* Add test to illustrate disappearing cookies

* Append cookie headers in newResponse
  • Loading branch information
codeflows authored May 18, 2024
1 parent 9540e69 commit ee9ccf8
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 4 deletions.
8 changes: 6 additions & 2 deletions deno_dist/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { HonoRequest } from './request.ts'
import type { Env, FetchEventLike, Input, NotFoundHandler, TypedResponse } from './types.ts'
import { HtmlEscapedCallbackPhase, resolveCallback } from './utils/html.ts'
import type { RedirectStatusCode, StatusCode } from './utils/http-status.ts'
import type { JSONValue, JSONParsed, IsAny, Simplify } from './utils/types.ts'
import type { IsAny, JSONParsed, JSONValue, Simplify } from './utils/types.ts'

type HeaderRecord = Record<string, string | string[]>
export type Data = string | ArrayBuffer | ReadableStream
Expand Down Expand Up @@ -380,7 +380,11 @@ export class Context<
if (this.#headers) {
// If the header is set by c.header() and arg.headers, c.header() will be prioritized.
this.#headers.forEach((v, k) => {
header.set(k, v)
if (k === 'set-cookie') {
header.append(k, v)
} else {
header.set(k, v)
}
})
}
const headers = setHeaders(header, this.#preparedHeaders)
Expand Down
16 changes: 16 additions & 0 deletions src/context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,22 @@ describe('Pass a ResponseInit to respond methods', () => {
expect(await res.text()).toBe('<h2>Hello</h2>')
})

it('c.body() should retain context cookies from context and original response', async () => {
setCookie(c, 'context', '1')
setCookie(c, 'context', '2')

const originalResponse = new Response('', {
headers: {
'set-cookie': 'response=1; Path=/',
},
})
const res = c.body('', originalResponse)
const cookies = res.headers.getSetCookie()
expect(cookies.includes('context=1; Path=/')).toBe(true)
expect(cookies.includes('context=2; Path=/')).toBe(true)
expect(cookies.includes('response=1; Path=/')).toBe(true)
})

it('c.text()', async () => {
const originalResponse = new Response(JSON.stringify({ foo: 'bar' }))
const res = c.text('foo', originalResponse)
Expand Down
8 changes: 6 additions & 2 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { HonoRequest } from './request'
import type { Env, FetchEventLike, Input, NotFoundHandler, TypedResponse } from './types'
import { HtmlEscapedCallbackPhase, resolveCallback } from './utils/html'
import type { RedirectStatusCode, StatusCode } from './utils/http-status'
import type { JSONValue, JSONParsed, IsAny, Simplify } from './utils/types'
import type { IsAny, JSONParsed, JSONValue, Simplify } from './utils/types'

type HeaderRecord = Record<string, string | string[]>
export type Data = string | ArrayBuffer | ReadableStream
Expand Down Expand Up @@ -380,7 +380,11 @@ export class Context<
if (this.#headers) {
// If the header is set by c.header() and arg.headers, c.header() will be prioritized.
this.#headers.forEach((v, k) => {
header.set(k, v)
if (k === 'set-cookie') {
header.append(k, v)
} else {
header.set(k, v)
}
})
}
const headers = setHeaders(header, this.#preparedHeaders)
Expand Down

0 comments on commit ee9ccf8

Please sign in to comment.