From b6a60ca30abd556e38e93ba93e040425af662439 Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Fri, 24 Jul 2026 11:22:18 +0900 Subject: [PATCH] fix(response): copy headers when init is a foreign Response --- src/response.ts | 11 +++-------- test/response.test.ts | 10 ++++++++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/response.ts b/src/response.ts index f1f6ccbd..2ba92cd0 100644 --- a/src/response.ts +++ b/src/response.ts @@ -46,21 +46,16 @@ export class Response { constructor(body?: BodyInit | null, init?: ResponseInit) { let headers: HeadersInit | undefined this.#body = body - if (init instanceof Response) { + if (init instanceof GlobalResponse) { const cachedGlobalResponse = (init as any)[responseCache] if (cachedGlobalResponse) { this.#init = cachedGlobalResponse // instantiate GlobalResponse cache and this object always returns value from global.Response this[getResponseCache]() return - } else { - this.#init = init.#init - // Read headers via the live getter so mutations made on `init` after - // construction (e.g. `init.headers.append('Set-Cookie', ...)`) are - // preserved on the clone. `new Headers(...)` still produces an - // independent copy so parent and child do not share the same object. - headers = new Headers(init.headers) } + this.#init = init instanceof Response ? init.#init : init + headers = new Headers(init.headers) } else { this.#init = init } diff --git a/test/response.test.ts b/test/response.test.ts index b75def31..48835420 100644 --- a/test/response.test.ts +++ b/test/response.test.ts @@ -139,6 +139,16 @@ describe('Response', () => { expect(res.headers.get('location')).toEqual('https://example.com/') }) + it('Should copy headers when rebuilding a response from fetch()', async () => { + const upstream = await fetch(`http://localhost:${port}`) + const rebuilt = new Response(upstream.body, upstream) + rebuilt.headers.set('x-test', '1') + expect(rebuilt.headers.get('x-test')).toEqual('1') + expect(rebuilt.headers.get('content-type')).toEqual('application/json charset=UTF-8') + expect(upstream.headers.get('x-test')).toBeNull() + expect(await rebuilt.json()).toEqual({ status: 'ok' }) + }) + it('Nested constructors should not cause an error even if ReadableStream is specified', async () => { const stream = new Response('hono').body const parentResponse = new Response(stream)