import assert from 'node:assert/strict'; import test from 'node:test'; import { readFileSync } from 'node:fs'; import { gunzipSync } from 'node:zlib'; import { createServer } from 'node:http'; import { once } from 'node:events'; import { buildingCompressionMiddleware } from '../scripts/building-compression.ts'; test('building transfer uses lossless gzip with automatic client decoding and identity fallback', async () => { const raw = readFileSync(new URL('../public/buildings/gwacheon.baked.bin', import.meta.url)); const gzip = readFileSync(new URL('../public/buildings/gwacheon.baked.bin.gz', import.meta.url)); assert.deepEqual(gunzipSync(gzip), raw); assert.ok(gzip.length < raw.length * 0.3); const middleware = buildingCompressionMiddleware(new URL('../public/', import.meta.url)); const server = createServer((req, res) => middleware(req, res, () => { res.setHeader('Content-Length', raw.length); res.end(req.method === 'HEAD' ? undefined : raw); })); server.listen(0, '127.0.0.1'); await once(server, 'listening'); const url = `http://127.0.0.1:${(server.address() as {port: number}).port}/buildings/gwacheon.baked.bin?v=test`; try { const response = await fetch(url, { headers: { 'Accept-Encoding': 'gzip' } }); assert.equal(response.headers.get('content-encoding'), 'gzip'); assert.equal(Number(response.headers.get('content-length')), gzip.length); assert.match(response.headers.get('vary')!, /Accept-Encoding/i); assert.deepEqual(Buffer.from(await response.arrayBuffer()), raw); const head = await fetch(url, { method: 'HEAD', headers: { 'Accept-Encoding': 'gzip' } }); assert.equal(head.headers.get('content-encoding'), 'gzip'); assert.equal((await head.arrayBuffer()).byteLength, 0); for (const encoding of ['identity', 'gzip;q=0', '*;q=1, gzip;q=0']) { const plain = await fetch(url, { headers: { 'Accept-Encoding': encoding } }); assert.equal(plain.headers.get('content-encoding'), null); assert.deepEqual(Buffer.from(await plain.arrayBuffer()), raw); } } finally { server.closeAllConnections(); await new Promise(resolve => server.close(() => resolve())); } });