Skip to content

Commit 1b22df0

Browse files
committed
fix transfer-encoding for all responses
- proxied response transfer-encoding is never relevant for the client response - need to reimplement transfer-encoding when proxying directly to the socket instead of the Response object
1 parent cfc4118 commit 1b22df0

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

lib/http-proxy/passes/web-outgoing.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,13 @@ export interface EditableResponse {
2727

2828
// If is a HTTP 1.0 request, remove chunk headers
2929
export function removeChunked(
30-
req: Request,
30+
_req: Request,
3131
_res: EditableResponse,
3232
// Response object from the proxy request
3333
proxyRes: ProxyResponse,
3434
) {
35-
if (req.httpVersion === "1.0") {
36-
delete proxyRes.headers["transfer-encoding"];
37-
}
35+
// transfer-encoding is hop-by-hop, don't preserve it across proxy hops
36+
delete proxyRes.headers["transfer-encoding"];
3837
}
3938

4039
// If is a HTTP 1.0 request, set the correct connection header

lib/http-proxy/passes/ws-incoming.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,16 +257,36 @@ export function stream(
257257
// note: none of these return anything
258258
pass(req, res as EditableResponse, proxyRes, options as NormalizedServerOptions & { target: NormalizeProxyTarget<ProxyTarget> });
259259
}
260-
// avoid Invalid character error in chunk size
261-
delete res.headers['transfer-encoding'];
260+
261+
// implement HTTP/1.1 chunked transfer unless content-length is defined
262+
// matches proxyRes.pipe(res) behavior,
263+
// but we are piping directly to the socket instead, so it's our job.
264+
let writeChunk = (chunk: Buffer | string) => {
265+
socket.write(chunk);
266+
}
267+
if (req.httpVersion === "1.1" && proxyRes.headers["content-length"] === undefined) {
268+
res.headers["transfer-encoding"] = "chunked";
269+
writeChunk = (chunk: Buffer | string) => {
270+
socket.write(chunk.length.toString(16));
271+
socket.write("\r\n");
272+
socket.write(chunk);
273+
socket.write("\r\n");
274+
}
275+
}
262276

263277
const proxyHead = createHttpHeader(
264278
`HTTP/${req.httpVersion} ${proxyRes.statusCode} ${proxyRes.statusMessage}`,
265279
res.headers,
266280
);
267281
if (!socket.destroyed) {
268282
socket.write(proxyHead);
269-
proxyRes.pipe(socket);
283+
proxyRes.on("data", (chunk) => {
284+
writeChunk(chunk);
285+
})
286+
proxyRes.on("end", () => {
287+
writeChunk("");
288+
socket.destroySoon();
289+
})
270290
} else {
271291
// make sure response is consumed
272292
proxyRes.resume();

0 commit comments

Comments
 (0)