mirror of
https://github.com/denoland/deno.git
synced 2025-01-11 08:33:43 -05:00
fix(ext/http): drop content-length header on compression (#13866)
This commit is contained in:
parent
4e1da28b39
commit
670aef5c1a
2 changed files with 71 additions and 1 deletions
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue