import { BASE_URL } from "../helpers.ts"; import { assertEquals } from "@std/assert"; import { Application } from "@oak/oak"; import { brotliDecompressSync, gunzipSync } from "node:zlib"; import { compressMiddleware } from "../../middleware/compress.ts"; const BIG = { success: true, data: { items: Array(200).fill("dump title") } }; function makeApp(): Application { const app = new Application(); app.use(compressMiddleware); app.use((ctx) => { const path = ctx.request.url.pathname; if (path === "/big") ctx.response.body = BIG; if (path === "/small") ctx.response.body = { success: true }; if (path === "/html") { ctx.response.type = "text/html"; ctx.response.body = `${"
gerbeur
".repeat(200)}`; } if (path === "/bytes") ctx.response.body = new Uint8Array(4096); if (path === "/encoded") { ctx.response.headers.set("Content-Encoding", "br"); ctx.response.type = "text/css"; ctx.response.body = "x".repeat(4096); } }); return app; } async function get(path: string, acceptEncoding?: string) { const res = await makeApp().handle( new Request(`${BASE_URL}${path}`, { headers: acceptEncoding ? { "Accept-Encoding": acceptEncoding } : {}, }), ); if (!res) throw new Error("no response"); return { res, bytes: new Uint8Array(await res.arrayBuffer()) }; } const text = (bytes: Uint8Array) => new TextDecoder().decode(bytes); Deno.test("compressMiddleware: JSON goes out in brotli, or gzip for a client without it", async () => { const br = await get("/big", "gzip, deflate, br"); assertEquals(br.res.headers.get("Content-Encoding"), "br"); assertEquals( br.res.headers.get("Content-Type"), "application/json; charset=UTF-8", ); assertEquals(br.res.headers.get("Vary"), "Accept-Encoding"); assertEquals(JSON.parse(text(brotliDecompressSync(br.bytes))), BIG); const gzip = await get("/big", "gzip"); assertEquals(gzip.res.headers.get("Content-Encoding"), "gzip"); assertEquals(JSON.parse(text(gunzipSync(gzip.bytes))), BIG); const refused = await get("/big", "br;q=0, gzip;q=0.5"); assertEquals(refused.res.headers.get("Content-Encoding"), "gzip"); }); Deno.test("compressMiddleware: a client that accepts no coding gets the JSON as it is", async () => { for (const accept of [undefined, "identity", "br;q=0"]) { const { res, bytes } = await get("/big", accept); assertEquals(res.headers.get("Content-Encoding"), null); // A cache still has to tell this answer from the compressed one. assertEquals(res.headers.get("Vary"), "Accept-Encoding"); assertEquals(JSON.parse(text(bytes)), BIG); } }); Deno.test("compressMiddleware: the HTML page is compressed too", async () => { const { res, bytes } = await get("/html", "br"); assertEquals(res.headers.get("Content-Encoding"), "br"); assertEquals(res.headers.get("Content-Type"), "text/html; charset=UTF-8"); assertEquals(text(brotliDecompressSync(bytes)).startsWith(" { const small = await get("/small", "br"); assertEquals(small.res.headers.get("Content-Encoding"), null); assertEquals(small.res.headers.get("Vary"), null); assertEquals(JSON.parse(text(small.bytes)), { success: true }); const bytes = await get("/bytes", "br"); assertEquals(bytes.res.headers.get("Content-Encoding"), null); assertEquals(bytes.bytes.length, 4096); const encoded = await get("/encoded", "br"); assertEquals(encoded.res.headers.get("Content-Encoding"), "br"); assertEquals(text(encoded.bytes), "x".repeat(4096)); });