From aa410e3dbada4ae2c4b33a1beb3e50892d750722 Mon Sep 17 00:00:00 2001 From: zibo Date: Thu, 22 Sep 2022 13:22:04 +0800 Subject: [PATCH 1/3] fix(http-proxy): remove disallowed headers when response header contains trailer Signed-off-by: zibo --- src/handlers/response-interceptor.ts | 23 +++++++++++++++++++++-- test/e2e/response-interceptor.spec.ts | 7 +++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/handlers/response-interceptor.ts b/src/handlers/response-interceptor.ts index cacadfb0..2cf529bf 100644 --- a/src/handlers/response-interceptor.ts +++ b/src/handlers/response-interceptor.ts @@ -13,6 +13,19 @@ type Interceptor = ( res: TRes, ) => Promise; +const TrailerDisallowHeaders: string[] = [ + 'content-length', + 'host', + 'content-type', + 'authorization', + 'cache-control', + 'max-forwards', + 'te', + 'set-cookie', + 'content-encoding', + 'content-range', +]; + /** * Intercept responses from upstream. * Automatically decompress (deflate, gzip, brotli). @@ -49,8 +62,14 @@ export function responseInterceptor< // set correct content-length (with double byte character support) debug('set content-length: %s', Buffer.byteLength(interceptedBuffer, 'utf8')); - res.setHeader('content-length', Buffer.byteLength(interceptedBuffer, 'utf8')); - + // some headers are disallowed when response headers contains trailer + if (proxyRes.headers.trailer === undefined) { + res.setHeader('content-length', Buffer.byteLength(interceptedBuffer, 'utf8')); + } else { + TrailerDisallowHeaders.forEach((value) => { + res.removeHeader(value); + }); + } debug('write intercepted response'); res.write(interceptedBuffer); res.end(); diff --git a/test/e2e/response-interceptor.spec.ts b/test/e2e/response-interceptor.spec.ts index dc11b6d4..6c378682 100644 --- a/test/e2e/response-interceptor.spec.ts +++ b/test/e2e/response-interceptor.spec.ts @@ -65,6 +65,13 @@ describe('responseInterceptor()', () => { const response = await agent.get(`/json`).expect(200); expect(response.body.favorite).toEqual('叉燒包'); }); + + it('should not contains disallow headers to trailer in response headers http://httpbin.org/response-headers', async () => { + const response = await agent + .get('/response-headers?Trailer=X-Stream-Error&Host=localhost') + .expect(200); + expect(response.header['host']).toBeUndefined(); + }); }); describe('intercept responses with original headers', () => { From 677e0fc06730138fa23555f41bb5ea40a9c87a68 Mon Sep 17 00:00:00 2001 From: zibo Date: Sun, 9 Oct 2022 10:34:40 +0800 Subject: [PATCH 2/3] Add link to verify the completeness disallow headers Signed-off-by: zibo --- src/handlers/response-interceptor.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/handlers/response-interceptor.ts b/src/handlers/response-interceptor.ts index 2cf529bf..a12070d9 100644 --- a/src/handlers/response-interceptor.ts +++ b/src/handlers/response-interceptor.ts @@ -13,6 +13,10 @@ type Interceptor = ( res: TRes, ) => Promise; +/** + * Disallow headers when response contains trailer + * source: https://developer.mozilla.org/docs/Web/HTTP/Headers/Trailer + */ const TrailerDisallowHeaders: string[] = [ 'content-length', 'host', From d852f09c90fde90640cb3f38ae2f748db3a06090 Mon Sep 17 00:00:00 2001 From: Steven Chim <655241+chimurai@users.noreply.github.com> Date: Tue, 21 Apr 2026 19:56:52 +0200 Subject: [PATCH 3/3] fix(responseInterceptor): fix test --- test/e2e/response-interceptor.spec.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/e2e/response-interceptor.spec.ts b/test/e2e/response-interceptor.spec.ts index 6c378682..4f675912 100644 --- a/test/e2e/response-interceptor.spec.ts +++ b/test/e2e/response-interceptor.spec.ts @@ -31,6 +31,15 @@ describe('responseInterceptor()', () => { 'content-type': 'image/png', }); + await targetServer + .forGet('/response-headers') + .withExactQuery('?Trailer=X-Stream-Error&Host=localhost') + .thenReply(200, '', { + 'transfer-encoding': 'chunked', + trailer: 'X-Stream-Error', + host: 'localhost', + }); + agent = request( createApp( createProxyMiddleware({ @@ -66,7 +75,7 @@ describe('responseInterceptor()', () => { expect(response.body.favorite).toEqual('叉燒包'); }); - it('should not contains disallow headers to trailer in response headers http://httpbin.org/response-headers', async () => { + it('should not contains disallow headers to trailer in response headers', async () => { const response = await agent .get('/response-headers?Trailer=X-Stream-Error&Host=localhost') .expect(200);