Skip to content

Commit

Permalink
fix(response interceptor): proxy original response headers (#563)
Browse files Browse the repository at this point in the history
  • Loading branch information
chimurai authored Apr 24, 2021
1 parent 017ac01 commit 88136d1
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 2 deletions.
34 changes: 32 additions & 2 deletions src/handlers/response-interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ export function responseInterceptor(interceptor: Interceptor) {
_proxyRes.on('data', (chunk) => (buffer = Buffer.concat([buffer, chunk])));

_proxyRes.on('end', async () => {
// set original content type from upstream
res.setHeader('content-type', originalProxyRes.headers['content-type'] || '');
// copy original headers
copyHeaders(proxyRes, res);

// call interceptor with intercepted response (buffer)
const interceptedBuffer = Buffer.from(await interceptor(buffer, originalProxyRes, req, res));
Expand Down Expand Up @@ -79,3 +79,33 @@ function decompress(proxyRes: http.IncomingMessage, contentEncoding: string) {

return _proxyRes;
}

/**
* Copy original headers
* https://github.com/apache/superset/blob/9773aba522e957ed9423045ca153219638a85d2f/superset-frontend/webpack.proxy-config.js#L78
*/
function copyHeaders(originalResponse, response) {
response.statusCode = originalResponse.statusCode;
response.statusMessage = originalResponse.statusMessage;

if (response.setHeader) {
let keys = Object.keys(originalResponse.headers);

// ignore chunked, brotli, gzip, deflate headers
keys = keys.filter((key) => !['content-encoding', 'transfer-encoding'].includes(key));

keys.forEach((key) => {
let value = originalResponse.headers[key];

if (key === 'set-cookie') {
// remove cookie domain
value = Array.isArray(value) ? value : [value];
value = value.map((x) => x.replace(/Domain=[^;]+?/i, ''));

This comment has been minimized.

Copy link
@dantman

dantman Jan 9, 2024

This line is turning cookie=value; Path=/; Domain=example.com; Max-Age=1800 into cookie=value; Path=/; xample.com; Max-Age=1800. Also I'm not sure why domain is being removed when this library is supposed to have a cookieDomainRewrite option that relies on the domain not being erased.

}

response.setHeader(key, value);
});
} else {
response.headers = originalResponse.headers;
}
}
26 changes: 26 additions & 0 deletions test/e2e/response-interceptor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,32 @@ describe('responseInterceptor()', () => {
});
});

describe('intercept responses with original headers', () => {
beforeEach(() => {
agent = request(
createApp(
createProxyMiddleware({
target: `http://httpbin.org`,
changeOrigin: true, // for vhosted sites, changes host header to match to target's host
selfHandleResponse: true,
onProxyRes: responseInterceptor(async (responseBuffer, proxyRes, req, res) => {
return responseBuffer;
}),
})
)
);
});

it('should proxy and return original headers from http://httpbin.org/cookies/set/cookie/monster', async () => {
return agent
.get(`/cookies/set/cookie/monster`)
.expect('Access-Control-Allow-Origin', '*')
.expect('Date', /.+/)
.expect('set-cookie', /.*cookie=monster.*/)
.expect(302);
});
});

describe('intercept compressed responses', () => {
beforeEach(() => {
agent = request(
Expand Down

0 comments on commit 88136d1

Please sign in to comment.