diff --git a/package-lock.json b/package-lock.json index c56b605c6..ee1587083 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@cfworker/json-schema": "^4.0.3", - "@hono/node-server": "^1.3.3", + "@hono/node-server": "^1.19.5", "@hono/node-ws": "^1.2.0", "@portkey-ai/mustache": "^2.1.3", "@smithy/signature-v4": "^2.1.1", @@ -1360,9 +1360,10 @@ } }, "node_modules/@hono/node-server": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.13.5.tgz", - "integrity": "sha512-lSo+CFlLqAFB4fX7ePqI9nauEn64wOfJHAfc9duYFTvAG3o416pC0nTGeNjuLHchLedH+XyWda5v79CVx1PIjg==", + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.5.tgz", + "integrity": "sha512-iBuhh+uaaggeAuf+TftcjZyWh2GEgZcVGXkNtskLVoWaXhnJtC5HLHrU8W1KHDoucqO1MswwglmkWLFyiDn4WQ==", + "license": "MIT", "engines": { "node": ">=18.14.1" }, diff --git a/package.json b/package.json index 845786981..fc501ad45 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@cfworker/json-schema": "^4.0.3", - "@hono/node-server": "^1.3.3", + "@hono/node-server": "^1.19.5", "@hono/node-ws": "^1.2.0", "@portkey-ai/mustache": "^2.1.3", "@smithy/signature-v4": "^2.1.1", diff --git a/src/handlers/services/responseService.ts b/src/handlers/services/responseService.ts index 8957ce5b2..b956806a1 100644 --- a/src/handlers/services/responseService.ts +++ b/src/handlers/services/responseService.ts @@ -61,7 +61,11 @@ export class ResponseService { )); } - this.updateHeaders(finalMappedResponse, cache.cacheStatus, retryAttempt); + finalMappedResponse = this.updateHeaders( + finalMappedResponse, + cache.cacheStatus, + retryAttempt + ); return { response: finalMappedResponse, @@ -99,6 +103,13 @@ export class ResponseService { cacheStatus: string | undefined, retryAttempt: number ) { + // Clone response and headers to work around `immutable` header guard + response = new Response(response.body, { + status: response.status, + statusText: response.statusText, + headers: new Headers(response.headers), + }); + // Append headers directly response.headers.append( RESPONSE_HEADER_KEYS.LAST_USED_OPTION_INDEX, diff --git a/tests/unit/src/handlers/services/responseService.test.ts b/tests/unit/src/handlers/services/responseService.test.ts index 597b480d4..0ef42b1b0 100644 --- a/tests/unit/src/handlers/services/responseService.test.ts +++ b/tests/unit/src/handlers/services/responseService.test.ts @@ -393,7 +393,7 @@ describe('ResponseService', () => { }); it('should add required headers', () => { - responseService.updateHeaders(mockResponse, 'HIT', 2); + mockResponse = responseService.updateHeaders(mockResponse, 'HIT', 2); expect( mockResponse.headers.get(RESPONSE_HEADER_KEYS.LAST_USED_OPTION_INDEX) @@ -411,14 +411,14 @@ describe('ResponseService', () => { }); it('should remove problematic headers', () => { - responseService.updateHeaders(mockResponse, undefined, 0); + mockResponse = responseService.updateHeaders(mockResponse, undefined, 0); expect(mockResponse.headers.get('content-length')).toBeNull(); expect(mockResponse.headers.get('transfer-encoding')).toBeNull(); }); it('should remove brotli encoding', () => { - responseService.updateHeaders(mockResponse, undefined, 0); + mockResponse = responseService.updateHeaders(mockResponse, undefined, 0); expect(mockResponse.headers.get('content-encoding')).toBeNull(); }); @@ -429,7 +429,7 @@ describe('ResponseService', () => { headers: { 'content-encoding': 'gzip' }, }); - responseService.updateHeaders(response, undefined, 0); + mockResponse = responseService.updateHeaders(response, undefined, 0); expect(response.headers.get('content-encoding')).toBeNull(); }); @@ -440,13 +440,13 @@ describe('ResponseService', () => { headers: { 'content-encoding': 'gzip' }, }); - responseService.updateHeaders(response, undefined, 0); + mockResponse = responseService.updateHeaders(response, undefined, 0); expect(response.headers.get('content-encoding')).toBe('gzip'); }); it('should not add cache status header when undefined', () => { - responseService.updateHeaders(mockResponse, undefined, 0); + mockResponse = responseService.updateHeaders(mockResponse, undefined, 0); expect( mockResponse.headers.get(RESPONSE_HEADER_KEYS.CACHE_STATUS) @@ -466,7 +466,7 @@ describe('ResponseService', () => { mockLogsService ); - serviceWithPortkey.updateHeaders(mockResponse, 'MISS', 0); + mockResponse = serviceWithPortkey.updateHeaders(mockResponse, 'MISS', 0); expect(mockResponse.headers.get(HEADER_KEYS.PROVIDER)).toBeNull(); }); @@ -484,7 +484,11 @@ describe('ResponseService', () => { mockLogsService ); - serviceWithEmptyProvider.updateHeaders(mockResponse, 'MISS', 0); + mockResponse = serviceWithEmptyProvider.updateHeaders( + mockResponse, + 'MISS', + 0 + ); expect(mockResponse.headers.get(HEADER_KEYS.PROVIDER)).toBeNull(); });