Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit d4de3a6

Browse files
committed
Retain Content-Length for custom Content-Encoding, closes #313
1 parent 9ce44ba commit d4de3a6

File tree

2 files changed

+61
-4
lines changed

2 files changed

+61
-4
lines changed

packages/http-server/src/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,6 @@ async function writeResponse(
177177
// we're responsible for doing so.
178178
const encoders: Transform[] = [];
179179
if (headers["content-encoding"] && response.encodeBody === "auto") {
180-
// Content-Length will be wrong as it's for the decoded length
181-
delete headers["content-length"];
182180
// Reverse of https://github.com/nodejs/undici/blob/48d9578f431cbbd6e74f77455ba92184f57096cf/lib/fetch/index.js#L1660
183181
const codings = headers["content-encoding"]
184182
.toString()
@@ -199,6 +197,10 @@ async function writeResponse(
199197
break;
200198
}
201199
}
200+
if (encoders.length > 0) {
201+
// Content-Length will be wrong as it's for the decoded length
202+
delete headers["content-length"];
203+
}
202204
}
203205

204206
// Add live reload script if enabled, this isn't an already encoded

packages/http-server/test/index.spec.ts

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,12 @@ const autoEncodeMacro: Macro<
523523
const port = await listen(t, http.createServer(createRequestListener(mf)));
524524
return new Promise<void>((resolve) => {
525525
http.get({ port }, async (res) => {
526-
t.is(res.headers["content-length"], undefined);
527-
t.is(res.headers["transfer-encoding"], "chunked");
526+
if (encodes) {
527+
t.is(res.headers["content-length"], undefined);
528+
t.is(res.headers["transfer-encoding"], "chunked");
529+
} else {
530+
t.not(res.headers["content-length"], undefined);
531+
}
528532
t.is(res.headers["content-encoding"], encoding);
529533
const compressed = await buffer(res);
530534
const decompressed = decompress(compressed);
@@ -614,6 +618,57 @@ test("createRequestListener: should allow connection close before stream finishe
614618
// This shouldn't throw a premature close
615619
await writer.write(utf8Encode("data: test\n\n"));
616620
});
621+
test("createRequestListener: should include Content-Length header on responses", async (t) => {
622+
// https://github.com/cloudflare/miniflare/issues/313
623+
const mf = useMiniflareWithHandler({ HTTPPlugin }, {}, (globals, req) => {
624+
const url = new globals.URL(req.url);
625+
if (url.pathname === "/content-encoding") {
626+
return new globals.Response("body", {
627+
headers: { "Content-Encoding": "custom", "Content-Length": "4" },
628+
});
629+
} else if (url.pathname === "/encode-body-manual") {
630+
return new globals.Response("body", {
631+
encodeBody: "manual",
632+
headers: { "Content-Length": "4" },
633+
});
634+
} else {
635+
return new globals.Response(null, { status: 404 });
636+
}
637+
});
638+
const port = await listen(t, http.createServer(createRequestListener(mf)));
639+
640+
// Check with custom `Content-Encoding` (https://github.com/cloudflare/miniflare/issues/312)
641+
await new Promise<void>((resolve) => {
642+
http.get({ port, path: "/content-encoding" }, async (res) => {
643+
t.is(res.headers["content-length"], "4");
644+
t.is(res.headers["content-encoding"], "custom");
645+
t.is(await text(res), "body");
646+
resolve();
647+
});
648+
});
649+
await new Promise<void>((resolve) => {
650+
http.get({ port, method: "HEAD", path: "/content-encoding" }, (res) => {
651+
t.is(res.headers["content-length"], "4");
652+
t.is(res.headers["content-encoding"], "custom");
653+
resolve();
654+
});
655+
});
656+
657+
// Check with `encodeBody: "manual"`
658+
await new Promise<void>((resolve) => {
659+
http.get({ port, path: "/encode-body-manual" }, async (res) => {
660+
t.is(res.headers["content-length"], "4");
661+
t.is(await text(res), "body");
662+
resolve();
663+
});
664+
});
665+
await new Promise<void>((resolve) => {
666+
http.get({ port, method: "HEAD", path: "/encode-body-manual" }, (res) => {
667+
t.is(res.headers["content-length"], "4");
668+
resolve();
669+
});
670+
});
671+
});
617672

618673
test("createServer: handles regular requests", async (t) => {
619674
const mf = useMiniflareWithHandler({ HTTPPlugin }, {}, (globals, req) => {

0 commit comments

Comments
 (0)