@fastify/compress 6.2.1 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,11 @@ name: CI
2
2
 
3
3
  on:
4
4
  push:
5
+ branches:
6
+ - main
7
+ - master
8
+ - next
9
+ - 'v*'
5
10
  paths-ignore:
6
11
  - 'docs/**'
7
12
  - '*.md'
package/README.md CHANGED
@@ -99,7 +99,8 @@ await fastify.register(
99
99
  )
100
100
  ```
101
101
  ### customTypes
102
- [mime-db](https://github.com/jshttp/mime-db) is used to determine if a `content-type` should be compressed. You can compress additional content types via regular expression.
102
+ [mime-db](https://github.com/jshttp/mime-db) is used to determine if a `content-type` should be compressed. You can compress additional content types via regular expression or by providing a function.
103
+
103
104
  ```javascript
104
105
  await fastify.register(
105
106
  import('@fastify/compress'),
@@ -107,6 +108,15 @@ await fastify.register(
107
108
  )
108
109
  ```
109
110
 
111
+ or
112
+
113
+ ```javascript
114
+ await fastify.register(
115
+ import('@fastify/compress'),
116
+ { customTypes: contentType => contentType.endsWith('x-protobuf') }
117
+ )
118
+ ```
119
+
110
120
  ### onUnsupportedEncoding
111
121
  When the encoding is not supported, a custom error response can be sent in place of the uncompressed payload by setting the `onUnsupportedEncoding(encoding, request, reply)` option to be a function that can modify the reply and return a `string | Buffer | Stream | Error` payload.
112
122
  ```javascript
package/index.js CHANGED
@@ -6,7 +6,7 @@ const pump = require('pump')
6
6
  const mimedb = require('mime-db')
7
7
  const intoStream = require('into-stream')
8
8
  const peek = require('peek-stream')
9
- const Minipass = require('minipass')
9
+ const { Minipass } = require('minipass')
10
10
  const pumpify = require('pumpify')
11
11
  const encodingNegotiator = require('@fastify/accept-negotiator')
12
12
  const { inherits, format } = require('util')
@@ -107,6 +107,8 @@ function fastifyCompress (fastify, opts, next) {
107
107
  next()
108
108
  }
109
109
 
110
+ const defaultCompressibleTypes = /^text\/(?!event-stream)|\+json$|\+text$|\+xml$|octet-stream$/
111
+
110
112
  function processCompressParams (opts) {
111
113
  /* istanbul ignore next */
112
114
  if (!opts) {
@@ -123,7 +125,11 @@ function processCompressParams (opts) {
123
125
  params.onUnsupportedEncoding = opts.onUnsupportedEncoding
124
126
  params.inflateIfDeflated = opts.inflateIfDeflated === true
125
127
  params.threshold = typeof opts.threshold === 'number' ? opts.threshold : 1024
126
- params.compressibleTypes = opts.customTypes instanceof RegExp ? opts.customTypes : /^text\/(?!event-stream)|\+json$|\+text$|\+xml$|octet-stream$/
128
+ params.compressibleTypes = opts.customTypes instanceof RegExp
129
+ ? opts.customTypes.test.bind(opts.customTypes)
130
+ : typeof opts.customTypes === 'function'
131
+ ? opts.customTypes
132
+ : defaultCompressibleTypes.test.bind(defaultCompressibleTypes)
127
133
  params.compressStream = {
128
134
  br: () => ((opts.zlib || zlib).createBrotliCompress || zlib.createBrotliCompress)(params.brotliOptions),
129
135
  gzip: () => ((opts.zlib || zlib).createGzip || zlib.createGzip)(params.zlibOptions),
@@ -461,7 +467,7 @@ function getEncodingHeader (encodings, request) {
461
467
  }
462
468
 
463
469
  function shouldCompress (type, compressibleTypes) {
464
- if (compressibleTypes.test(type)) return true
470
+ if (compressibleTypes(type)) return true
465
471
  const data = mimedb[type.split(';', 1)[0].trim().toLowerCase()]
466
472
  if (data === undefined) return false
467
473
  return data.compressible === true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastify/compress",
3
- "version": "6.2.1",
3
+ "version": "6.3.0",
4
4
  "description": "Fastify compression utils",
5
5
  "main": "index.js",
6
6
  "types": "types/index.d.ts",
@@ -9,14 +9,14 @@
9
9
  "fastify-plugin": "^4.0.0",
10
10
  "into-stream": "^6.0.0",
11
11
  "mime-db": "^1.51.0",
12
- "minipass": "^4.0.0",
12
+ "minipass": "^5.0.0",
13
13
  "peek-stream": "^1.1.3",
14
14
  "pump": "^3.0.0",
15
15
  "pumpify": "^2.0.1"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@fastify/pre-commit": "^2.0.2",
19
- "@types/node": "^18.0.0",
19
+ "@types/node": "^20.1.0",
20
20
  "@typescript-eslint/eslint-plugin": "^5.9.0",
21
21
  "@typescript-eslint/parser": "^5.9.0",
22
22
  "adm-zip": "^0.5.9",
@@ -785,6 +785,29 @@ test('It should not compress :', async (t) => {
785
785
  t.equal(response.statusCode, 200)
786
786
  })
787
787
 
788
+ t.test('when `customTypes` is a function and returns false on the provided `Content-Type` reply header`', async (t) => {
789
+ t.plan(2)
790
+
791
+ const fastify = Fastify()
792
+ await fastify.register(compressPlugin, { customTypes: value => value === 'application/x-user-header' })
793
+
794
+ fastify.get('/', (request, reply) => {
795
+ reply
796
+ .type('application/x-other-type')
797
+ .compress(createReadStream('./package.json'))
798
+ })
799
+
800
+ const response = await fastify.inject({
801
+ url: '/',
802
+ method: 'GET',
803
+ headers: {
804
+ 'accept-encoding': 'gzip'
805
+ }
806
+ })
807
+ t.notOk(response.headers['content-encoding'])
808
+ t.equal(response.statusCode, 200)
809
+ })
810
+
788
811
  t.test('when `X-No-Compression` request header is `true`', async (t) => {
789
812
  t.plan(3)
790
813
 
@@ -2443,7 +2466,31 @@ test('It should compress data if `customTypes` is set and matches `Content-Type`
2443
2466
  t.equal(payload.toString('utf-8'), file)
2444
2467
  })
2445
2468
 
2446
- test('It should not apply `customTypes` option if the passed value is not a RegExp', async (t) => {
2469
+ test('It should compress data if `customTypes` is a function and returns true on the provided `Content-Type` reply header value', async (t) => {
2470
+ t.plan(2)
2471
+ const fastify = Fastify()
2472
+ await fastify.register(compressPlugin, { customTypes: value => value === 'application/x-user-header' })
2473
+
2474
+ fastify.get('/', (request, reply) => {
2475
+ reply
2476
+ .type('application/x-user-header')
2477
+ .send(createReadStream('./package.json'))
2478
+ })
2479
+
2480
+ const response = await fastify.inject({
2481
+ url: '/',
2482
+ method: 'GET',
2483
+ headers: {
2484
+ 'accept-encoding': 'gzip'
2485
+ }
2486
+ })
2487
+ const file = readFileSync('./package.json', 'utf8')
2488
+ const payload = zlib.gunzipSync(response.rawPayload)
2489
+ t.equal(response.headers['content-encoding'], 'gzip')
2490
+ t.equal(payload.toString('utf-8'), file)
2491
+ })
2492
+
2493
+ test('It should not apply `customTypes` option if the passed value is not a RegExp or Function', async (t) => {
2447
2494
  t.plan(2)
2448
2495
 
2449
2496
  const fastify = Fastify()
package/types/index.d.ts CHANGED
@@ -59,11 +59,13 @@ type RouteDecompressOptions = Pick<fastifyCompress.FastifyCompressOptions,
59
59
 
60
60
  type EncodingToken = 'br' | 'deflate' | 'gzip' | 'identity';
61
61
 
62
+ type CompressibleContentTypeFunction = (contentType: string) => boolean;
63
+
62
64
  declare namespace fastifyCompress {
63
65
 
64
66
  export interface FastifyCompressOptions {
65
67
  brotliOptions?: BrotliOptions;
66
- customTypes?: RegExp;
68
+ customTypes?: RegExp | CompressibleContentTypeFunction;
67
69
  encodings?: EncodingToken[];
68
70
  forceRequestEncoding?: EncodingToken;
69
71
  global?: boolean;
@@ -28,6 +28,10 @@ const withGlobalOptions: FastifyCompressOptions = {
28
28
  const app: FastifyInstance = fastify()
29
29
  app.register(fastifyCompress, withGlobalOptions)
30
30
 
31
+ app.register(fastifyCompress, {
32
+ customTypes: value => value === 'application/json'
33
+ })
34
+
31
35
  app.get('/test-one', async (request, reply) => {
32
36
  expectType<void>(reply.compress(stream))
33
37
  })