From 0dd117fb26aa8169a806e0a43415e4b90464e07e Mon Sep 17 00:00:00 2001 From: Richard Petersen <richard.petersen@open-xchange.com> Date: Tue, 8 Nov 2022 12:47:33 +0100 Subject: [PATCH] add: OXUI-1083 - Support for brotli compression --- spec/file_caching_test.js | 35 ++++++++++++++++++++++++++--------- src/files.js | 10 ++++++++-- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/spec/file_caching_test.js b/spec/file_caching_test.js index 94490a4..e25c1bb 100644 --- a/spec/file_caching_test.js +++ b/spec/file_caching_test.js @@ -394,24 +394,41 @@ describe('File caching service', function () { }) }) - it('serves files as gzip', async function () { + it('serves index.html gzip compressed', async function () { mockFetch({ 'http://ui-server': { '/manifest.json': generateSimpleViteManifest({}), - '/large.js': () => new Response([...new Array(2500)].join(' '), { headers: { 'content-type': 'application/javascript' } }) + '/index.html': () => new Response([...new Array(2500)].join(' '), { headers: { 'content-type': 'text/html' } }) } }) app = await mockApp() - const response = await request(app.server).get('/large.js') + const response = await request(app.server).get('/index.html') expect(response.statusCode).to.equal(200) expect(response.headers['content-encoding']).to.equal('gzip') // check for files in redis - expect(zlib.gunzipSync(await redis.client.getBuffer('ui-middleware:554855300:/large.js:body')).toString()).to.equal(response.text) + expect(zlib.gunzipSync(await redis.client.getBuffer('ui-middleware:554855300:/index.html:body')).toString()).to.equal(response.text) }) - it('does not serve small files with gzip', async function () { + it('serves files as brotli compressed', async function () { + mockFetch({ + 'http://ui-server': { + '/manifest.json': generateSimpleViteManifest({}), + '/large.js': () => new Response([...new Array(2500)].join('a'), { headers: { 'content-type': 'application/javascript' } }) + } + }) + app = await mockApp() + + const response = await request(app.server).get('/large.js') + expect(response.statusCode).to.equal(200) + expect(response.headers['content-encoding']).to.equal('br') + + // check for files in redis + expect((await redis.client.getBuffer('ui-middleware:554855300:/large.js:body')).toString()).to.equal(response.text) + }) + + it('does not serve small files with compression', async function () { mockFetch({ 'http://ui-server': { '/manifest.json': generateSimpleViteManifest({}), @@ -428,7 +445,7 @@ describe('File caching service', function () { expect((await redis.client.getBuffer('ui-middleware:554855300:/small.js:body')).toString()).to.equal(response.text) }) - it('does not serve other mime types with gzip', async function () { + it('does not serve other mime types with compression', async function () { mockFetch({ 'http://ui-server': { '/manifest.json': generateSimpleViteManifest({}), @@ -445,7 +462,7 @@ describe('File caching service', function () { expect(await redis.client.getBuffer('ui-middleware:554855300:/file.mp3:body')).to.deep.equal(response.body) }) - it('does server svg as gzip (also escapes chars in regex)', async function () { + it('does serve svg with brotli compression (also escapes chars in regex)', async function () { mockFetch({ 'http://ui-server': { '/manifest.json': generateSimpleViteManifest({}), @@ -456,9 +473,9 @@ describe('File caching service', function () { const response = await request(app.server).get('/file.svg') expect(response.statusCode).to.equal(200) - expect(response.headers['content-encoding']).to.equal('gzip') + expect(response.headers['content-encoding']).to.equal('br') // check for files in redis - expect(zlib.gunzipSync(await redis.client.getBuffer('ui-middleware:554855300:/file.svg:body'))).to.deep.equal(response.body) + expect(await redis.client.getBuffer('ui-middleware:554855300:/file.svg:body')).to.deep.equal(response.body) }) }) diff --git a/src/files.js b/src/files.js index 7fbdfb9..757ff49 100644 --- a/src/files.js +++ b/src/files.js @@ -8,6 +8,7 @@ import zlib from 'node:zlib' import { promisify } from 'node:util' const gzip = promisify(zlib.gzip) +const brotliCompress = promisify(zlib.brotliCompress) const compressFileSize = Number(process.env.COMPRESS_FILE_SIZE) const compressionMimeTypes = (process.env.COMPRESS_FILE_TYPES || '').replace(/([.+*?^$()[\]{}|])/g, '\\$1').split(' ') @@ -52,8 +53,13 @@ export async function fetchFileWithHeadersFromBaseUrl (path, baseUrl, version) { } if (result.body.length > compressFileSize && compressionWhitelistRegex.test(result.headers['content-type'])) { - result.body = await gzip(result.body) - result.headers['content-encoding'] = 'gzip' + if (path === '/index.html') { + result.body = await gzip(result.body) + result.headers['content-encoding'] = 'gzip' + } else { + result.body = await brotliCompress(result.body) + result.headers['content-encoding'] = 'br' + } } return result -- GitLab