Skip to content

Commit

Permalink
fix: default brotliOptions does not applied to createBrotliCompress a…
Browse files Browse the repository at this point in the history
…nd createBrotliDecompress (#284)

* fix: default brotliOptions does not applied to createBrotliCompress and createBrotliDecompress

* Polish test cases

* Only override default compress level for global options (route specific compress will be merged with global options anyway)

* Cosmetic changes

* Fix type tests error
  • Loading branch information
stanleyxu2005 authored Mar 27, 2024
1 parent dd59de3 commit 46ce8f9
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 33 deletions.
18 changes: 11 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ function fastifyCompress (fastify, opts, next) {
}

const defaultCompressibleTypes = /^text\/(?!event-stream)|(?:\+|\/)json(?:;|$)|(?:\+|\/)text(?:;|$)|(?:\+|\/)xml(?:;|$)|octet-stream(?:;|$)/u
const recommendedDefaultBrotliOptions = {
params: {
// Default of 4 as 11 has a heavy impact on performance.
// https://blog.cloudflare.com/this-is-brotli-from-origin#testing
[zlib.constants.BROTLI_PARAM_QUALITY]: 4
}
}

function processCompressParams (opts) {
/* istanbul ignore next */
Expand All @@ -117,16 +124,13 @@ function processCompressParams (opts) {
}

const params = {
global: (typeof opts.global === 'boolean') ? opts.global : true,
/**
* Default of 4 as 11 has a heavy impact on performance.
* @see {@link https://blog.cloudflare.com/this-is-brotli-from-origin#testing}
*/
brotliOptions: { [zlib.constants.BROTLI_PARAM_QUALITY]: 4, ...opts.brotliOptions }
global: (typeof opts.global === 'boolean') ? opts.global : true
}

params.removeContentLengthHeader = typeof opts.removeContentLengthHeader === 'boolean' ? opts.removeContentLengthHeader : true
params.brotliOptions = opts.brotliOptions
params.brotliOptions = params.global
? { ...recommendedDefaultBrotliOptions, ...opts.brotliOptions }
: opts.brotliOptions
params.zlibOptions = opts.zlibOptions
params.onUnsupportedEncoding = opts.onUnsupportedEncoding
params.inflateIfDeflated = opts.inflateIfDeflated === true
Expand Down
79 changes: 56 additions & 23 deletions test/global-compress.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2534,36 +2534,69 @@ test('When `encodings` option is set, it should only use the registered value',
t.equal(response.statusCode, 200)
})

test('It should send data compressed according to `brotliOptions`', async (t) => {
t.plan(2)
const brotliOptions = {
params: {
[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
[zlib.constants.BROTLI_PARAM_QUALITY]: 4
test('It should send data compressed according to `brotliOptions` :', async (t) => {
t.test('when using br encoding', async (t) => {
t.plan(3)
const brotliOptions = {
params: {
[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
[zlib.constants.BROTLI_PARAM_QUALITY]: 8
}
}
}

const fastify = Fastify()
await fastify.register(compressPlugin, { global: true, brotliOptions })
const fastify = Fastify()
await fastify.register(compressPlugin, { global: true, brotliOptions })

fastify.get('/', (request, reply) => {
reply
.type('text/plain')
.compress(createReadStream('./package.json'))
fastify.get('/', (request, reply) => {
reply
.type('text/plain')
.compress(createReadStream('./package.json'))
})

const response = await fastify.inject({
url: '/',
method: 'GET',
headers: {
'accept-encoding': 'br'
}
})

const file = readFileSync('./package.json', 'utf8')
const payload = zlib.brotliDecompressSync(response.rawPayload, brotliOptions)
t.equal(response.headers['content-encoding'], 'br')
t.equal(payload.toString('utf-8'), file)

const compressedPayload = zlib.brotliCompressSync(file, brotliOptions)
t.same(response.rawPayload, compressedPayload)
})

const response = await fastify.inject({
url: '/',
method: 'GET',
headers: {
'accept-encoding': 'br'
t.test('default BROTLI_PARAM_QUALITY to be 4', async (t) => {
t.plan(1)

const fastify = Fastify()
await fastify.register(compressPlugin, { global: true })

const file = readFileSync('./package.json', 'utf8')
fastify.get('/', (request, reply) => {
reply
.type('text/plain')
.compress(file)
})

const response = await fastify.inject({
url: '/',
method: 'GET',
headers: {
'accept-encoding': 'br'
}
})

const defaultBrotliOptions = {
params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 4 }
}
const compressedPayload = zlib.brotliCompressSync(file, defaultBrotliOptions)
t.same(response.rawPayload, compressedPayload)
})

const file = readFileSync('./package.json', 'utf8')
const payload = zlib.brotliDecompressSync(response.rawPayload, brotliOptions)
t.equal(response.headers['content-encoding'], 'br')
t.equal(payload.toString('utf-8'), file)
})

test('It should send data compressed according to `zlibOptions` :', async (t) => {
Expand Down
6 changes: 3 additions & 3 deletions types/index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ app.get('/test-two', async (request, reply) => {
expectError(reply.compress())
})

// Instanciation of an app without global
// Instantiation of an app without global
const appWithoutGlobal: FastifyInstance = fastify()
appWithoutGlobal.register(fastifyCompress, { global: false })

Expand Down Expand Up @@ -107,11 +107,11 @@ appWithoutGlobal.inject(
}
},
(err) => {
expectType<Error>(err)
expectType<Error | undefined>(err)
}
)

// Instanciation of an app that should trigger a typescript error
// Instantiation of an app that should trigger a typescript error
const appThatTriggerAnError = fastify()
expectError(appThatTriggerAnError.register(fastifyCompress, {
global: true,
Expand Down

0 comments on commit 46ce8f9

Please sign in to comment.