fix(server): strip compression headers in generic OpenCode proxy (#795)
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Bohdan Triapitsyn
parent
060b37777c
commit
58d7713581
@@ -0,0 +1,61 @@
|
||||
const filteredRequestHeaders = new Set([
|
||||
'host',
|
||||
'connection',
|
||||
'content-length',
|
||||
'transfer-encoding',
|
||||
'keep-alive',
|
||||
'te',
|
||||
'trailer',
|
||||
'upgrade',
|
||||
'accept-encoding',
|
||||
]);
|
||||
|
||||
const filteredResponseHeaders = new Set([
|
||||
'connection',
|
||||
'content-length',
|
||||
'transfer-encoding',
|
||||
'keep-alive',
|
||||
'te',
|
||||
'trailer',
|
||||
'upgrade',
|
||||
'www-authenticate',
|
||||
'content-encoding',
|
||||
]);
|
||||
|
||||
export const collectForwardProxyHeaders = (requestHeaders, authHeaders = {}) => {
|
||||
const headers = {};
|
||||
|
||||
for (const [key, value] of Object.entries(requestHeaders || {})) {
|
||||
if (!value) continue;
|
||||
const normalizedKey = key.toLowerCase();
|
||||
if (filteredRequestHeaders.has(normalizedKey)) continue;
|
||||
headers[normalizedKey] = Array.isArray(value) ? value.join(', ') : String(value);
|
||||
}
|
||||
|
||||
if (authHeaders.Authorization) {
|
||||
headers.Authorization = authHeaders.Authorization;
|
||||
}
|
||||
|
||||
return headers;
|
||||
};
|
||||
|
||||
export const shouldForwardProxyResponseHeader = (key) => {
|
||||
if (typeof key !== 'string' || key.trim().length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !filteredResponseHeaders.has(key.toLowerCase());
|
||||
};
|
||||
|
||||
export const applyForwardProxyResponseHeaders = (responseHeaders, response) => {
|
||||
if (!responseHeaders || typeof response?.setHeader !== 'function') {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const [key, value] of responseHeaders.entries()) {
|
||||
if (!shouldForwardProxyResponseHeader(key)) {
|
||||
continue;
|
||||
}
|
||||
response.setHeader(key, value);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
import { describe, expect, it } from 'bun:test';
|
||||
|
||||
import {
|
||||
applyForwardProxyResponseHeaders,
|
||||
collectForwardProxyHeaders,
|
||||
shouldForwardProxyResponseHeader,
|
||||
} from './proxy-headers.js';
|
||||
|
||||
describe('OpenCode proxy header handling', () => {
|
||||
it('drops accept-encoding from forwarded request headers', () => {
|
||||
const headers = collectForwardProxyHeaders({
|
||||
accept: 'application/json',
|
||||
'accept-encoding': 'gzip, deflate, br',
|
||||
connection: 'keep-alive',
|
||||
});
|
||||
|
||||
expect(headers.accept).toBe('application/json');
|
||||
expect(headers['accept-encoding']).toBeUndefined();
|
||||
});
|
||||
|
||||
it('drops content-encoding from forwarded response headers', () => {
|
||||
expect(shouldForwardProxyResponseHeader('content-encoding')).toBe(false);
|
||||
expect(shouldForwardProxyResponseHeader('Content-Encoding')).toBe(false);
|
||||
});
|
||||
|
||||
it('still keeps ordinary response headers', () => {
|
||||
expect(shouldForwardProxyResponseHeader('content-type')).toBe(true);
|
||||
expect(shouldForwardProxyResponseHeader('etag')).toBe(true);
|
||||
});
|
||||
|
||||
it('applies upstream response headers to express response without content-encoding', () => {
|
||||
const applied = [];
|
||||
const response = {
|
||||
setHeader(key, value) {
|
||||
applied.push([key, value]);
|
||||
},
|
||||
};
|
||||
|
||||
applyForwardProxyResponseHeaders(
|
||||
new Headers({
|
||||
'content-type': 'application/json',
|
||||
etag: 'W/"abc"',
|
||||
'content-encoding': 'gzip',
|
||||
}),
|
||||
response,
|
||||
);
|
||||
|
||||
expect(applied).toEqual([
|
||||
['content-type', 'application/json'],
|
||||
['etag', 'W/"abc"'],
|
||||
]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user