Skip to content
Snippets Groups Projects
Commit 867770f7 authored by richard.petersen's avatar richard.petersen :sailboat:
Browse files

OXUI-1084: Serve /manifests calls with compression

parent 0dd117fb
No related branches found
No related tags found
No related merge requests found
import request from 'supertest'
import { generateSimpleViteManifest, mockApp, mockConfig, mockFetch, mockRedis } from './util.js'
import { brotliParser, generateSimpleViteManifest, mockApp, mockConfig, mockFetch, mockRedis } from './util.js'
import { expect } from 'chai'
import * as td from 'testdouble'
import RedisMock from 'ioredis-mock'
......@@ -29,6 +29,19 @@ describe('UI Middleware', function () {
it('fetches manifest data', async function () {
const response = await request(app.server).get('/manifests')
expect(response.statusCode).to.equal(200)
expect(response.headers['content-encoding']).to.equal('gzip')
expect(response.body).to.deep.equal([{ namespace: 'test', path: 'example' }])
})
it('fetches manifest data with brotli', async function () {
const response = await request(app.server)
.get('/manifests')
.set('accept-encoding', 'deflate, gzip, br')
.buffer(true)
.parse(brotliParser)
expect(response.statusCode).to.equal(200)
expect(response.headers['content-encoding']).to.equal('br')
expect(response.headers['content-type']).to.equal('application/json; charset=utf-8')
expect(response.body).to.deep.equal([{ namespace: 'test', path: 'example' }])
})
......
import * as td from 'testdouble'
import { register } from 'prom-client'
import RedisMock from 'ioredis-mock'
import zlib from 'node:zlib'
export function generateSimpleViteManifest (mapping) {
const viteManifest = {}
......@@ -64,3 +65,17 @@ export async function mockApp () {
await app.listen({ port: 0 })
return app
}
export async function brotliParser (res, cb) {
const brotli = zlib.createBrotliDecompress()
let buffer = Buffer.from('')
res.pipe(brotli)
brotli.on('data', chunk => (buffer = Buffer.concat([buffer, chunk])))
brotli.on('end', () => {
let result = buffer.toString()
if (res.headers['content-type'].startsWith('application/json')) {
result = JSON.parse(result)
}
cb(null, result)
})
}
......@@ -2,6 +2,9 @@ import { configMap } from './configMap.js'
import { getRedisKey, viteManifestToDeps, viteToOxManifest } from './util.js'
import { logger } from './logger.js'
import * as cache from './cache.js'
import zlib from 'node:zlib'
import { promisify } from 'node:util'
const brotliCompress = promisify(zlib.brotliCompress)
export async function fetchViteManifests () {
// vite manifests contains a set of objects with the vite-manifests
......@@ -32,9 +35,15 @@ export async function getViteManifests ({ version }) {
}
export function getOxManifests ({ version }) {
return cache.get(getRedisKey({ version, name: 'oxManifests' }), async () => {
return cache.getFile({ name: 'oxManifests', version }, async () => {
const headers = { 'content-type': 'application/json; charset=utf-8', 'content-encoding': 'br' }
const viteManifests = await getViteManifests({ version })
return viteToOxManifest(viteManifests)
const oxManifests = await viteToOxManifest(viteManifests)
const body = await brotliCompress(JSON.stringify(oxManifests))
return {
body,
headers
}
})
}
......
import { getOxManifests } from '../manifests.js'
export default async function manifestsPlugin (fastify, options) {
fastify.get('/manifests', async (req, res) => {
if (res.body) return
res.send(await getOxManifests({ version: res.version }))
fastify.get('/manifests', async (req, reply) => {
if (reply.body) return
const { body, headers } = await getOxManifests({ version: reply.version })
reply.headers(headers)
reply.send(body)
})
}
......@@ -11,9 +11,7 @@ export default async function serveFilePlugin (fastify, options) {
const path = url === '/' ? '/index.html' : url
const { body, headers } = await getFile({ version, path })
Object.entries(headers).forEach(([key, value]) => {
reply.header(key, value)
})
reply.headers(headers)
reply.send(body)
} catch (err) {
const errors = err.errors || [err]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment