From a5ef7eaf0c37229ca3211a740cc2fc59fc04c9c6 Mon Sep 17 00:00:00 2001 From: Michael Solomon Date: Thu, 2 Jan 2025 19:44:13 +0200 Subject: [PATCH] fix(ClientRequest): prevent `rawHeaders` from being shared across instances (#694) Co-authored-by: Artem Zakharchenko --- .../ClientRequest/utils/recordRawHeaders.test.ts | 15 +++++++++++++++ .../ClientRequest/utils/recordRawHeaders.ts | 9 ++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/interceptors/ClientRequest/utils/recordRawHeaders.test.ts b/src/interceptors/ClientRequest/utils/recordRawHeaders.test.ts index 0f3a4035..75071260 100644 --- a/src/interceptors/ClientRequest/utils/recordRawHeaders.test.ts +++ b/src/interceptors/ClientRequest/utils/recordRawHeaders.test.ts @@ -241,3 +241,18 @@ it('does not throw on using Headers before recording', () => { request.headers.set('X-My-Header', '1') expect(getRawFetchHeaders(request.headers)).toEqual([['X-My-Header', '1']]) }) + +/** + * @see https://github.com/mswjs/interceptors/issues/681 + */ +it('isolates headers between different headers instances', async () => { + recordRawFetchHeaders() + const original = new Headers() + const firstClone = new Headers(original) + firstClone.set('Content-Type', 'application/json') + const secondClone = new Headers(original) + + expect(original.get('Content-Type')).toBeNull() + expect(firstClone.get('Content-Type')).toBe('application/json') + expect(secondClone.get('Content-Type')).toBeNull() +}) diff --git a/src/interceptors/ClientRequest/utils/recordRawHeaders.ts b/src/interceptors/ClientRequest/utils/recordRawHeaders.ts index 1e4c0fe9..80902d50 100644 --- a/src/interceptors/ClientRequest/utils/recordRawHeaders.ts +++ b/src/interceptors/ClientRequest/utils/recordRawHeaders.ts @@ -118,7 +118,14 @@ export function recordRawFetchHeaders() { [Reflect.get(headersInit, kRawHeaders)], newTarget ) - ensureRawHeadersSymbol(headers, Reflect.get(headersInit, kRawHeaders)) + ensureRawHeadersSymbol(headers, [ + /** + * @note Spread the retrieved headers to clone them. + * This prevents multiple Headers instances from pointing + * at the same internal "rawHeaders" array. + */ + ...Reflect.get(headersInit, kRawHeaders), + ]) return headers }