0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

fix(ext/http): make serveHttp compress for Accept-Encoding: deflate, gzip (#14525)

This commit is contained in:
Andy Kurnia 2022-05-13 20:10:05 +08:00 committed by GitHub
parent eed7afc3aa
commit 42fec5150e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 4 deletions

View file

@ -1918,6 +1918,66 @@ Deno.test({
},
});
Deno.test({
name: "http server compresses when accept-encoding is deflate, gzip",
permissions: { net: true, run: 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"), "deflate, gzip");
const body = "x".repeat(10000);
contentLength = String(body.length);
const response = new Response(
body,
{
headers: {
"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,
// "--compressed", // Windows curl does not support --compressed
"--header",
"Accept-Encoding: deflate, gzip",
];
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: 80\r\n"));
proc.close();
}
await Promise.all([server(), client()]);
},
});
Deno.test("upgradeHttp tcp", async () => {
async function client() {
const tcpConn = await Deno.connect({ port: 4501 });

View file

@ -392,10 +392,28 @@ async fn op_http_accept(
{
let mut accept_encoding = stream.accept_encoding.borrow_mut();
*accept_encoding = fly_accept_encoding::parse(request.headers())
.ok()
.flatten()
.unwrap_or(Encoding::Identity);
// curl --compressed sends "Accept-Encoding: deflate, gzip".
// fly_accept_encoding::parse() returns Encoding::Deflate.
// Deno does not support Encoding::Deflate.
// So, Deno used no compression, although gzip was possible.
// This patch makes Deno use gzip instead in this case.
*accept_encoding = Encoding::Identity;
let mut max_qval = 0.0;
if let Ok(encodings) = fly_accept_encoding::encodings(request.headers()) {
for (encoding, qval) in encodings {
if let Some(enc @ (Encoding::Brotli | Encoding::Gzip)) = encoding {
// this logic came from fly_accept_encoding.
if (qval - 1.0f32).abs() < 0.01 {
*accept_encoding = enc;
break;
} else if qval > max_qval {
*accept_encoding = enc;
max_qval = qval;
}
}
}
}
}
let method = request.method().to_string();