mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -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 {
|
function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
|
||||||
// Based on https://tools.ietf.org/html/rfc2616#section-19.4.6
|
// Based on https://tools.ietf.org/html/rfc2616#section-19.4.6
|
||||||
const tp = new TextProtoReader(r);
|
const tp = new TextProtoReader(r);
|
||||||
|
|
|
@ -610,6 +610,10 @@ async fn op_http_write_headers(
|
||||||
body_compressible && data.len() > 20 && accepts_compression;
|
body_compressible && data.len() > 20 && accepts_compression;
|
||||||
|
|
||||||
if should_compress {
|
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
|
// If user provided a ETag header for uncompressed data, we need to
|
||||||
// ensure it is a Weak Etag header ("W/").
|
// ensure it is a Weak Etag header ("W/").
|
||||||
if let Some(value) = etag_header {
|
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
|
// https://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_comp_level
|
||||||
let mut writer = GzEncoder::new(Vec::new(), Compression::new(1));
|
let mut writer = GzEncoder::new(Vec::new(), Compression::new(1));
|
||||||
writer.write_all(&data.into_bytes())?;
|
writer.write_all(&data.into_bytes())?;
|
||||||
body = builder.body(writer.finish().unwrap().into())?;
|
body = builder.body(writer.finish()?.into())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Reference in a new issue