diff --git a/src/handlers/response-interceptor.ts b/src/handlers/response-interceptor.ts index 5ddc310f..794c58e2 100644 --- a/src/handlers/response-interceptor.ts +++ b/src/handlers/response-interceptor.ts @@ -12,6 +12,23 @@ type Interceptor = ( res: http.ServerResponse ) => Promise; +/** + * Disallow headers when response contains trailer + * source: https://developer.mozilla.org/docs/Web/HTTP/Headers/Trailer + */ +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). @@ -45,8 +62,14 @@ export function responseInterceptor(interceptor: Interceptor) { // 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 38c07c20..a431b250 100644 --- a/test/e2e/response-interceptor.spec.ts +++ b/test/e2e/response-interceptor.spec.ts @@ -41,6 +41,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', () => {