summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/tests/unit/http_test.ts503
1 files changed, 501 insertions, 2 deletions
diff --git a/cli/tests/unit/http_test.ts b/cli/tests/unit/http_test.ts
index 5ff1475b3..68500006f 100644
--- a/cli/tests/unit/http_test.ts
+++ b/cli/tests/unit/http_test.ts
@@ -95,7 +95,7 @@ Deno.test(
const resp = new Uint8Array(200);
const readResult = await conn.read(resp);
- assertEquals(readResult, 115);
+ assertEquals(readResult, 138);
conn.close();
@@ -1165,7 +1165,7 @@ Deno.test(
const resp = new Uint8Array(200);
const readResult = await conn.read(resp);
- assertEquals(readResult, 115);
+ assertEquals(readResult, 138);
conn.close();
@@ -1173,6 +1173,505 @@ Deno.test(
},
);
+/* Automatic Body Compression */
+
+const decoder = new TextDecoder();
+
+Deno.test({
+ name: "http server compresses body",
+ permissions: { net: true },
+ async fn() {
+ const hostname = "localhost";
+ const port = 4501;
+
+ 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 response = new Response(
+ JSON.stringify({ hello: "deno", now: "with", compressed: "body" }),
+ {
+ headers: { "content-type": "application/json" },
+ },
+ );
+ 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"));
+ proc.close();
+ }
+
+ await Promise.all([server(), client()]);
+ },
+});
+
+Deno.test({
+ name: "http server doesn't compress small body",
+ permissions: { net: true },
+ async fn() {
+ const hostname = "localhost";
+ const port = 4501;
+
+ 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 response = new Response(
+ JSON.stringify({ hello: "deno" }),
+ {
+ headers: { "content-type": "application/json" },
+ },
+ );
+ 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()).toLocaleLowerCase();
+ assert(output.includes("vary: accept-encoding\r\n"));
+ assert(!output.includes("content-encoding: "));
+ proc.close();
+ }
+
+ await Promise.all([server(), client()]);
+ },
+});
+
+Deno.test({
+ name: "http server respects accept-encoding weights",
+ permissions: { net: true },
+ async fn() {
+ const hostname = "localhost";
+ const port = 4501;
+
+ 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;q=0.8, br;q=1.0, *;q=0.1",
+ );
+ const response = new Response(
+ JSON.stringify({ hello: "deno", now: "with", compressed: "body" }),
+ {
+ headers: { "content-type": "application/json" },
+ },
+ );
+ 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;q=0.8, br;q=1.0, *;q=0.1",
+ ];
+ 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: br\r\n"));
+ proc.close();
+ }
+
+ await Promise.all([server(), client()]);
+ },
+});
+
+Deno.test({
+ name: "http server augments vary header",
+ permissions: { net: true },
+ async fn() {
+ const hostname = "localhost";
+ const port = 4501;
+
+ 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 response = new Response(
+ JSON.stringify({ hello: "deno", now: "with", compressed: "body" }),
+ {
+ headers: { "content-type": "application/json", vary: "Accept" },
+ },
+ );
+ 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, Accept\r\n"));
+ assert(output.includes("content-encoding: gzip\r\n"));
+ proc.close();
+ }
+
+ await Promise.all([server(), client()]);
+ },
+});
+
+Deno.test({
+ name: "http server weakens etag header",
+ permissions: { net: true },
+ async fn() {
+ const hostname = "localhost";
+ const port = 4501;
+
+ 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 response = new Response(
+ JSON.stringify({ hello: "deno", now: "with", compressed: "body" }),
+ {
+ headers: {
+ "content-type": "application/json",
+ etag: "33a64df551425fcc55e4d42a148795d9f25f89d4",
+ },
+ },
+ );
+ 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("etag: W/33a64df551425fcc55e4d42a148795d9f25f89d4\r\n"),
+ );
+ assert(output.includes("content-encoding: gzip\r\n"));
+ proc.close();
+ }
+
+ await Promise.all([server(), client()]);
+ },
+});
+
+Deno.test({
+ name: "http server passes through weak etag header",
+ permissions: { net: true },
+ async fn() {
+ const hostname = "localhost";
+ const port = 4501;
+
+ 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 response = new Response(
+ JSON.stringify({ hello: "deno", now: "with", compressed: "body" }),
+ {
+ headers: {
+ "content-type": "application/json",
+ etag: "W/33a64df551425fcc55e4d42a148795d9f25f89d4",
+ },
+ },
+ );
+ 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("etag: W/33a64df551425fcc55e4d42a148795d9f25f89d4\r\n"),
+ );
+ assert(output.includes("content-encoding: gzip\r\n"));
+ proc.close();
+ }
+
+ await Promise.all([server(), client()]);
+ },
+});
+
+Deno.test({
+ name: "http server doesn't compress body when no-transform is set",
+ permissions: { net: true },
+ async fn() {
+ const hostname = "localhost";
+ const port = 4501;
+
+ 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 response = new Response(
+ JSON.stringify({ hello: "deno", now: "with", compressed: "body" }),
+ {
+ headers: {
+ "content-type": "application/json",
+ "cache-control": "no-transform",
+ },
+ },
+ );
+ 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: "));
+ proc.close();
+ }
+
+ await Promise.all([server(), client()]);
+ },
+});
+
+Deno.test({
+ name: "http server doesn't compress body when content-range is set",
+ permissions: { net: true },
+ async fn() {
+ const hostname = "localhost";
+ const port = 4501;
+
+ 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 response = new Response(
+ JSON.stringify({ hello: "deno", now: "with", compressed: "body" }),
+ {
+ headers: {
+ "content-type": "application/json",
+ "content-range": "bytes 200-100/67589",
+ },
+ },
+ );
+ 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: "));
+ proc.close();
+ }
+
+ await Promise.all([server(), client()]);
+ },
+});
+
+Deno.test({
+ name: "http server doesn't compress streamed bodies",
+ permissions: { net: true },
+ async fn() {
+ const hostname = "localhost";
+ const port = 4501;
+
+ async function server() {
+ const encoder = new TextEncoder();
+ 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 bodyInit = new ReadableStream({
+ start(controller) {
+ controller.enqueue(
+ encoder.encode(
+ JSON.stringify({
+ hello: "deno",
+ now: "with",
+ compressed: "body",
+ }),
+ ),
+ );
+ controller.close();
+ },
+ });
+ const response = new Response(
+ bodyInit,
+ {
+ headers: { "content-type": "application/json", vary: "Accept" },
+ },
+ );
+ 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\r\n"));
+ assert(!output.includes("content-encoding: "));
+ 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);