0.2.6-dev: brotli (quality 5) on the fly with the existing memory cache for clients that name br, gzip for the rest; separate ETags per encoding (measured against gzip-6: .skel −27 %, data JSON −26 %, vendor −14 %, scripts −5 %) — host bandwidth layer 1.4; golden: unchanged

This commit is contained in:
sganggs committed 2026-10-12 16:29:52 +08:00
1 parent 35b09bb63b
commit 0bb16fd616
8 files changed
+173 -59

No files matched your search

+53 -11
View File
@@ -11,7 +11,7 @@ import path from 'node:path';
import { randomBytes } from 'node:crypto';
import { setTimeout as delay } from 'node:timers/promises';
import { startServer, parseRange, acceptsGzip, parseTrustProxy } from '../server/index.js';
import { startServer, parseRange, acceptsGzip, pickEncoding, parseTrustProxy } from '../server/index.js';
import { loadData, lookup, getChess, getBond, getBand, getMode, getConfig, INDEXED_FILES } from '../server/data.js';
import * as dataModule from '../server/data.js';
import { CODE_ALPHABET, BOT_NAMES } from '../server/lobby.js';
@@ -109,6 +109,8 @@ describe('static http server', () => {
const js = `// app\n${'export const x = 1;\n'.repeat(200)}`;
const mp3 = randomBytes(5000);
const skel = Buffer.from('skel'.repeat(400));
// over the 8 MB compression cache limit: compressed as a stream
const big = `// big\n${Array.from({ length: 360000 }, (_, i) => `export const v${i} = ${i % 97};`).join('\n')}\n`;
before(async () => {
tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'sp-static-'));
@@ -127,6 +129,7 @@ describe('static http server', () => {
w('public/assets/spine/x.skel', skel);
w('public/assets/spine/x.atlas', 'x.png\nsize: 64,64\n'.repeat(40));
w('public/assets/img/a.png', randomBytes(32));
w('public/js/huge.js', big);
w('public/assets/img/a.webp', randomBytes(32));
w('public/fonts/f.woff2', randomBytes(32));
w('public/fonts/f.ttf', randomBytes(32));
@@ -164,17 +167,20 @@ describe('static http server', () => {
assert.equal(redirect.headers.location, '/sub/?x=1');
});
test('javascript: correct MIME, gzip when accepted, identity otherwise', async () => {
const gz = await httpReq(srv.port, '/js/app.js', { headers: { 'accept-encoding': 'gzip, deflate, br' } });
assert.equal(gz.status, 200);
assert.equal(gz.headers['content-type'], 'text/javascript; charset=utf-8');
assert.equal(gz.headers['content-encoding'], 'gzip');
assert.equal(gz.headers.vary, 'Accept-Encoding');
assert.equal(Number(gz.headers['content-length']), gz.body.length);
test('javascript: correct MIME, brotli when named, gzip when accepted, identity otherwise', async () => {
const br = await httpReq(srv.port, '/js/app.js', { headers: { 'accept-encoding': 'gzip, deflate, br' } });
assert.equal(br.status, 200);
assert.equal(br.headers['content-type'], 'text/javascript; charset=utf-8');
assert.equal(br.headers['content-encoding'], 'br', 'a browser on an HTTPS page (or localhost) names br');
assert.equal(br.headers.vary, 'Accept-Encoding');
assert.equal(Number(br.headers['content-length']), br.body.length);
assert.equal(zlib.brotliDecompressSync(br.body).toString(), js);
const gz = await httpReq(srv.port, '/js/app.js', { headers: { 'accept-encoding': 'gzip, deflate' } });
assert.equal(gz.headers['content-encoding'], 'gzip', 'a LAN http:// page: gzip');
assert.equal(zlib.gunzipSync(gz.body).toString(), js);
// cached second response is identical
const gz2 = await httpReq(srv.port, '/js/app.js', { headers: { 'accept-encoding': 'gzip' } });
assert.deepEqual(gz2.body, gz.body);
// cached second responses are identical
assert.deepEqual((await httpReq(srv.port, '/js/app.js', { headers: { 'accept-encoding': 'gzip' } })).body, gz.body);
assert.deepEqual((await httpReq(srv.port, '/js/app.js', { headers: { 'accept-encoding': 'br' } })).body, br.body);
const plain = await httpReq(srv.port, '/js/app.js');
assert.equal(plain.headers['content-encoding'], undefined);
@@ -209,6 +215,27 @@ describe('static http server', () => {
}
const skelGz = await httpReq(srv.port, '/assets/spine/x.skel', { headers: { 'accept-encoding': 'gzip' } });
assert.deepEqual(zlib.gunzipSync(skelGz.body), skel);
const skelBr = await httpReq(srv.port, '/assets/spine/x.skel', { headers: { 'accept-encoding': 'gzip, br' } });
assert.equal(skelBr.headers['content-encoding'], 'br');
assert.deepEqual(zlib.brotliDecompressSync(skelBr.body), skel);
// media is never compressed, whatever the client names
assert.equal((await httpReq(srv.port, '/assets/audio/bgm.mp3', { headers: { 'accept-encoding': 'br, gzip' } })).headers['content-encoding'], undefined);
assert.equal((await httpReq(srv.port, '/assets/img/a.png', { headers: { 'accept-encoding': 'br' } })).headers['content-encoding'], undefined);
});
test('a file over the compression cache limit is compressed as a stream (brotli and gzip); HEAD sends no body', async () => {
const br = await httpReq(srv.port, '/js/huge.js', { headers: { 'accept-encoding': 'br' } });
assert.equal(br.headers['content-encoding'], 'br');
assert.equal(br.headers['content-length'], undefined, 'streamed: no length up front');
assert.equal(zlib.brotliDecompressSync(br.body).toString(), big);
assert.ok(br.body.length < big.length / 4);
const gz = await httpReq(srv.port, '/js/huge.js', { headers: { 'accept-encoding': 'gzip' } });
assert.equal(gz.headers['content-encoding'], 'gzip');
assert.equal(zlib.gunzipSync(gz.body).toString(), big);
const head = await httpReq(srv.port, '/js/huge.js', { method: 'HEAD', headers: { 'accept-encoding': 'br' } });
assert.equal(head.status, 200);
assert.equal(head.body.length, 0);
assert.equal(head.headers['content-encoding'], 'br');
});
test('ETag / Last-Modified revalidation and Cache-Control policy', async () => {
@@ -228,6 +255,10 @@ describe('static http server', () => {
assert.equal(stale.status, 200);
const gzEtag = (await httpReq(srv.port, '/js/app.js', { headers: { 'accept-encoding': 'gzip' } })).headers.etag;
assert.notEqual(gzEtag, etag, 'gzip variant has its own ETag');
const brEtag = (await httpReq(srv.port, '/js/app.js', { headers: { 'accept-encoding': 'br' } })).headers.etag;
assert.equal(brEtag, etag.replace(/"$/, '-br"'), 'so has the brotli variant');
assert.equal((await httpReq(srv.port, '/js/app.js', { headers: { 'accept-encoding': 'br', 'if-none-match': brEtag } })).status, 304);
assert.equal((await httpReq(srv.port, '/js/app.js', { headers: { 'accept-encoding': 'gzip', 'if-none-match': brEtag } })).status, 200, 'not the gzip variant');
// unversioned art/fonts/vendor: cached for a day (files can be rewritten in place by the asset tools); the art and
// fonts carry their content hash as ETag (server/http/assetIndex.js), so a rewrite with the same bytes is a 304
@@ -396,6 +427,17 @@ describe('static http server', () => {
assert.equal(acceptsGzip('*;q=0'), false);
assert.equal(acceptsGzip('br'), false);
assert.equal(acceptsGzip(undefined), false);
// brotli when named at least as high as gzip; `*` alone never picks it
assert.equal(pickEncoding('gzip, deflate, br, zstd'), 'br');
assert.equal(pickEncoding('gzip, deflate'), 'gzip');
assert.equal(pickEncoding('br;q=0, gzip'), 'gzip');
assert.equal(pickEncoding('br;q=0.5, gzip'), 'gzip');
assert.equal(pickEncoding('gzip;q=0.5, br'), 'br');
assert.equal(pickEncoding('br'), 'br');
assert.equal(pickEncoding('*'), 'gzip');
assert.equal(pickEncoding('*;q=0'), null);
assert.equal(pickEncoding('identity'), null);
assert.equal(pickEncoding(undefined), null);
});
});