summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/tests/unit/http_test.ts66
-rw-r--r--ext/http/lib.rs6
2 files changed, 71 insertions, 1 deletions
diff --git a/cli/tests/unit/http_test.ts b/cli/tests/unit/http_test.ts
index 68500006f..65ee55577 100644
--- a/cli/tests/unit/http_test.ts
+++ b/cli/tests/unit/http_test.ts
@@ -1672,6 +1672,72 @@ Deno.test({
},
});
+Deno.test({
+ name: "http server updates content-length header if compression is applied",
+ permissions: { net: true },
+ async fn() {
+ const hostname = "localhost";
+ const port = 4501;
+ let contentLength: string;
+
+ async function server() {
+ const listener = Deno.listen({ hostname, port });
+ const tcpConn = await listener.accept();
+ const httpConn = Deno.serveHttp(tcpConn);
+ const e = await httpConn.nextRequest();
+ assert(e);
+ const { request, respondWith } = e;
+ assertEquals(request.headers.get("Accept-Encoding"), "gzip, deflate, br");
+ const body = JSON.stringify({
+ hello: "deno",
+ now: "with",
+ compressed: "body",
+ });
+ contentLength = String(body.length);
+ const response = new Response(
+ body,
+ {
+ headers: {
+ "content-type": "application/json",
+ "content-length": contentLength,
+ },
+ },
+ );
+ await respondWith(response);
+ httpConn.close();
+ listener.close();
+ }
+
+ async function client() {
+ const url = `http://${hostname}:${port}/`;
+ const cmd = [
+ "curl",
+ "-I",
+ "--request",
+ "GET",
+ "--url",
+ url,
+ "--header",
+ "Accept-Encoding: gzip, deflate, br",
+ ];
+ const proc = Deno.run({ cmd, stdout: "piped", stderr: "null" });
+ const status = await proc.status();
+ assert(status.success);
+ const output = decoder.decode(await proc.output());
+ assert(output.includes("vary: Accept-Encoding\r\n"));
+ assert(output.includes("content-encoding: gzip\r\n"));
+ // Ensure the content-length header is updated.
+ assert(!output.includes(`content-length: ${contentLength}\r\n`));
+ assert(output.includes("content-length: 72\r\n"));
+ console.log(output);
+
+ proc.close();
+ }
+
+ await Promise.all([server(), client()]);
+ },
+});
+
function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
// Based on https://tools.ietf.org/html/rfc2616#section-19.4.6
const tp = new TextProtoReader(r);
diff --git a/ext/http/lib.rs b/ext/http/lib.rs
index b70bed464..ae5ddb9c3 100644
--- a/ext/http/lib.rs
+++ b/ext/http/lib.rs
@@ -610,6 +610,10 @@ async fn op_http_write_headers(
body_compressible && data.len() > 20 && accepts_compression;
if should_compress {
+ // Drop 'content-length' header. Hyper will update it using compressed body.
+ if let Some(headers) = builder.headers_mut() {
+ headers.remove("content-length");
+ }
// If user provided a ETag header for uncompressed data, we need to
// ensure it is a Weak Etag header ("W/").
if let Some(value) = etag_header {
@@ -646,7 +650,7 @@ async fn op_http_write_headers(
// https://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_comp_level
let mut writer = GzEncoder::new(Vec::new(), Compression::new(1));
writer.write_all(&data.into_bytes())?;
- body = builder.body(writer.finish().unwrap().into())?;
+ body = builder.body(writer.finish()?.into())?;
}
}
} else {