@fastify/compress 6.4.0 → 7.0.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.
package/.gitattributes ADDED
@@ -0,0 +1,2 @@
1
+ # Set default behavior to automatically convert line endings
2
+ * text=auto eol=lf
package/.taprc CHANGED
@@ -1,6 +1,2 @@
1
- ts: false
2
- jsx: false
3
- flow: false
4
- coverage: true
5
- check-coverage: true
6
- 100: true
1
+ files:
2
+ - test/**/*.test.js
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![NPM version](https://img.shields.io/npm/v/@fastify/compress.svg?style=flat)](https://www.npmjs.com/package/@fastify/compress)
5
5
  [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)
6
6
 
7
- Adds compression utils to [the Fastify `reply` object](https://www.fastify.io/docs/latest/Reference/Reply/#reply) and a hook to decompress requests payloads.
7
+ Adds compression utils to [the Fastify `reply` object](https://fastify.dev/docs/latest/Reference/Reply/#reply) and a hook to decompress requests payloads.
8
8
  Supports `gzip`, `deflate`, and `brotli`.
9
9
 
10
10
  > **Important note:** since `@fastify/compress` version 4.x payloads that are compressed using the `zip` algorithm are not automatically uncompressed anymore. `@fastify/compress` main feature is to provide response compression mechanism to your server, however the `zip` format does not appear in the [IANA maintained Table of Content Encodings](https://www.iana.org/assignments/http-parameters/http-parameters.xml#content-coding) and thus such behavior was out of the scope of this plugin.
@@ -169,7 +169,7 @@ You can tune compression by setting the `brotliOptions` and `zlibOptions` proper
169
169
  brotliOptions: {
170
170
  params: {
171
171
  [zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT, // useful for APIs that primarily return text
172
- [zlib.constants.BROTLI_PARAM_QUALITY]: 4, // default is 11, max is 11, min is 0
172
+ [zlib.constants.BROTLI_PARAM_QUALITY]: 4, // default is 4, max is 11, min is 0
173
173
  },
174
174
  },
175
175
  zlibOptions: {
package/index.js CHANGED
@@ -1,15 +1,16 @@
1
1
  'use strict'
2
2
 
3
+ const zlib = require('node:zlib')
4
+ const { inherits, format } = require('node:util')
5
+
3
6
  const fp = require('fastify-plugin')
4
- const zlib = require('zlib')
7
+ const encodingNegotiator = require('@fastify/accept-negotiator')
5
8
  const pump = require('pump')
6
9
  const mimedb = require('mime-db')
7
10
  const intoStream = require('into-stream')
8
11
  const peek = require('peek-stream')
9
12
  const { Minipass } = require('minipass')
10
13
  const pumpify = require('pumpify')
11
- const encodingNegotiator = require('@fastify/accept-negotiator')
12
- const { inherits, format } = require('util')
13
14
 
14
15
  const { isStream, isGzip, isDeflate } = require('./lib/utils')
15
16
 
@@ -50,12 +51,12 @@ function fastifyCompress (fastify, opts, next) {
50
51
  // add onSend hook onto each route as needed
51
52
  fastify.addHook('onRoute', (routeOptions) => {
52
53
  // If route config.compress has been set it takes precedence over compress
53
- if (routeOptions.config && typeof routeOptions.config.compress !== 'undefined') {
54
+ if (routeOptions.config?.compress !== undefined) {
54
55
  routeOptions.compress = routeOptions.config.compress
55
56
  }
56
57
 
57
58
  // Manage compression options
58
- if (typeof routeOptions.compress !== 'undefined') {
59
+ if (routeOptions.compress !== undefined) {
59
60
  if (typeof routeOptions.compress === 'object') {
60
61
  const mergedCompressParams = Object.assign(
61
62
  {}, globalCompressParams, processCompressParams(routeOptions.compress)
@@ -79,12 +80,12 @@ function fastifyCompress (fastify, opts, next) {
79
80
  }
80
81
 
81
82
  // If route config.decompress has been set it takes precedence over compress
82
- if (routeOptions.config && typeof routeOptions.config.decompress !== 'undefined') {
83
+ if (routeOptions.config?.decompress !== undefined) {
83
84
  routeOptions.decompress = routeOptions.config.decompress
84
85
  }
85
86
 
86
87
  // Manage decompression options
87
- if (typeof routeOptions.decompress !== 'undefined') {
88
+ if (routeOptions.decompress !== undefined) {
88
89
  if (typeof routeOptions.decompress === 'object') {
89
90
  // if the current endpoint has a custom compress configuration ...
90
91
  const mergedDecompressParams = Object.assign(
@@ -107,7 +108,7 @@ function fastifyCompress (fastify, opts, next) {
107
108
  next()
108
109
  }
109
110
 
110
- const defaultCompressibleTypes = /^text\/(?!event-stream)|(\+|\/)json(;|$)|(\+|\/)text(;|$)|(\+|\/)xml(;|$)|octet-stream(;|$)/
111
+ const defaultCompressibleTypes = /^text\/(?!event-stream)|(?:\+|\/)json(?:;|$)|(?:\+|\/)text(?:;|$)|(?:\+|\/)xml(?:;|$)|octet-stream(?:;|$)/u
111
112
 
112
113
  function processCompressParams (opts) {
113
114
  /* istanbul ignore next */
@@ -116,7 +117,12 @@ function processCompressParams (opts) {
116
117
  }
117
118
 
118
119
  const params = {
119
- global: (typeof opts.global === 'boolean') ? opts.global : true
120
+ global: (typeof opts.global === 'boolean') ? opts.global : true,
121
+ /**
122
+ * Default of 4 as 11 has a heavy impact on performance.
123
+ * @see {@link https://blog.cloudflare.com/this-is-brotli-from-origin#testing}
124
+ */
125
+ brotliOptions: { [zlib.constants.BROTLI_PARAM_QUALITY]: 4, ...opts.brotliOptions }
120
126
  }
121
127
 
122
128
  params.removeContentLengthHeader = typeof opts.removeContentLengthHeader === 'boolean' ? opts.removeContentLengthHeader : true
@@ -452,6 +458,8 @@ function onDecompressError (request, params, encoding, error) {
452
458
  Object.assign(error, errorPayload)
453
459
  }
454
460
 
461
+ const gzipAlias = /\*|x-gzip/gu
462
+
455
463
  function getEncodingHeader (encodings, request) {
456
464
  let header = request.headers['accept-encoding']
457
465
  if (header != null) {
@@ -459,7 +467,7 @@ function getEncodingHeader (encodings, request) {
459
467
  // consider the no-preference token as gzip for downstream compat
460
468
  // and x-gzip as an alias of gzip
461
469
  // ref.: [HTTP/1.1 RFC 7230 section 4.2.3](https://datatracker.ietf.org/doc/html/rfc7230#section-4.2.3)
462
- .replace(/\*|x-gzip/g, 'gzip')
470
+ .replace(gzipAlias, 'gzip')
463
471
  return encodingNegotiator.negotiate(header, encodings)
464
472
  } else {
465
473
  return undefined
package/package.json CHANGED
@@ -1,44 +1,42 @@
1
1
  {
2
2
  "name": "@fastify/compress",
3
- "version": "6.4.0",
3
+ "version": "7.0.0",
4
4
  "description": "Fastify compression utils",
5
5
  "main": "index.js",
6
+ "type": "commonjs",
6
7
  "types": "types/index.d.ts",
7
8
  "dependencies": {
8
- "@fastify/accept-negotiator": "^1.0.0",
9
- "fastify-plugin": "^4.0.0",
9
+ "@fastify/accept-negotiator": "^1.1.0",
10
+ "fastify-plugin": "^4.5.0",
10
11
  "into-stream": "^6.0.0",
11
- "mime-db": "^1.51.0",
12
- "minipass": "^6.0.0",
12
+ "mime-db": "^1.52.0",
13
+ "minipass": "^7.0.2",
13
14
  "peek-stream": "^1.1.3",
14
15
  "pump": "^3.0.0",
15
16
  "pumpify": "^2.0.1"
16
17
  },
17
18
  "devDependencies": {
18
19
  "@fastify/pre-commit": "^2.0.2",
19
- "@types/node": "^20.1.0",
20
- "@typescript-eslint/eslint-plugin": "^5.9.0",
21
- "@typescript-eslint/parser": "^5.9.0",
22
- "adm-zip": "^0.5.9",
23
- "fastify": "^4.0.0-rc.2",
20
+ "@types/node": "^20.4.2",
21
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
22
+ "@typescript-eslint/parser": "^6.0.0",
23
+ "adm-zip": "^0.5.10",
24
+ "fastify": "^4.19.2",
24
25
  "jsonstream": "^1.0.3",
25
- "standard": "^17.0.0",
26
- "tap": "^16.0.0",
27
- "tsd": "^0.28.0",
28
- "typescript": "^5.0.2"
26
+ "standard": "^17.1.0",
27
+ "tap": "^16.3.7",
28
+ "tsd": "^0.30.0",
29
+ "typescript": "^5.1.6"
29
30
  },
30
31
  "scripts": {
31
- "coverage": "npm run unit -- --cov",
32
- "coverage-report": "npm run coverage -- --coverage-report=lcov",
32
+ "coverage": "npm run test:unit -- --coverage-report=html",
33
33
  "lint": "standard",
34
34
  "lint:fix": "npm run lint -- --fix",
35
- "lint:typescript": "npm run lint:fix -- --parser @typescript-eslint/parser --plugin typescript test/types/*.ts",
36
- "lint:types": "npm run lint:fix -- --parser @typescript-eslint/parser --plugin typescript *.d.ts",
37
- "test": "npm run lint && npm run unit && npm run test:typescript",
35
+ "lint:fix:typescript": "npm run lint:fix -- --parser @typescript-eslint/parser --plugin @typescript-eslint/eslint-plugin \"**/*.d.ts\"",
36
+ "test": "npm run test:unit && npm run test:typescript",
38
37
  "test:typescript": "tsd",
39
- "unit": "tap -J test/*.test.js",
40
- "unit:report": "npm run unit -- --cov --coverage-report=html",
41
- "unit:verbose": "npm run unit -- -Rspec"
38
+ "test:unit": "tap",
39
+ "test:unit:verbose": "npm run test:unit -- -Rspec"
42
40
  },
43
41
  "keywords": [
44
42
  "fastify",
@@ -1,14 +1,14 @@
1
1
  'use strict'
2
2
 
3
3
  const { test } = require('tap')
4
- const { createReadStream, readFile, readFileSync } = require('fs')
5
- const { Readable, Writable, PassThrough } = require('stream')
6
- const zlib = require('zlib')
4
+ const { createReadStream, readFile, readFileSync } = require('node:fs')
5
+ const { Readable, Writable, PassThrough } = require('node:stream')
6
+ const zlib = require('node:zlib')
7
7
  const AdmZip = require('adm-zip')
8
8
  const JSONStream = require('jsonstream')
9
9
  const Fastify = require('fastify')
10
10
  const compressPlugin = require('../index')
11
- const { once } = require('events')
11
+ const { once } = require('node:events')
12
12
 
13
13
  test('When `global` is not set, it is `true` by default :', async (t) => {
14
14
  t.test('it should compress Buffer data using brotli when `Accept-Encoding` request header is `br`', async (t) => {
@@ -766,7 +766,7 @@ test('It should not compress :', async (t) => {
766
766
  t.plan(2)
767
767
 
768
768
  const fastify = Fastify()
769
- await fastify.register(compressPlugin, { customTypes: /x-user-header$/ })
769
+ await fastify.register(compressPlugin, { customTypes: /x-user-header$/u })
770
770
 
771
771
  fastify.get('/', (request, reply) => {
772
772
  reply
@@ -1101,7 +1101,7 @@ test('It should not compress :', async (t) => {
1101
1101
  t.plan(2)
1102
1102
 
1103
1103
  const fastify = Fastify()
1104
- await fastify.register(compressPlugin, { customTypes: /x-user-header$/ })
1104
+ await fastify.register(compressPlugin, { customTypes: /x-user-header$/u })
1105
1105
 
1106
1106
  fastify.get('/', (request, reply) => {
1107
1107
  reply
@@ -1442,7 +1442,7 @@ test('It should not double-compress :', async (t) => {
1442
1442
  })
1443
1443
  const payload = zlib.brotliDecompressSync(response.rawPayload)
1444
1444
  t.equal(response.headers['content-encoding'], 'br')
1445
- t.equal(response.headers['content-length'], response.rawPayload.length)
1445
+ t.equal(response.headers['content-length'], response.rawPayload.length.toString())
1446
1446
  t.equal(payload.toString('utf-8'), file)
1447
1447
  })
1448
1448
 
@@ -1472,7 +1472,7 @@ test('It should not double-compress :', async (t) => {
1472
1472
  })
1473
1473
  const payload = zlib.inflateSync(response.rawPayload)
1474
1474
  t.equal(response.headers['content-encoding'], 'deflate')
1475
- t.equal(response.headers['content-length'], response.rawPayload.length)
1475
+ t.equal(response.headers['content-length'], response.rawPayload.length.toString())
1476
1476
  t.equal(payload.toString('utf-8'), file)
1477
1477
  })
1478
1478
 
@@ -1502,7 +1502,7 @@ test('It should not double-compress :', async (t) => {
1502
1502
  })
1503
1503
  const payload = zlib.gunzipSync(response.rawPayload)
1504
1504
  t.equal(response.headers['content-encoding'], 'gzip')
1505
- t.equal(response.headers['content-length'], response.rawPayload.length)
1505
+ t.equal(response.headers['content-length'], response.rawPayload.length.toString())
1506
1506
  t.equal(payload.toString('utf-8'), file)
1507
1507
  })
1508
1508
  })
@@ -2445,7 +2445,7 @@ test('`Accept-Encoding` request header values :', async (t) => {
2445
2445
  test('It should compress data if `customTypes` is set and matches `Content-Type` reply header value', async (t) => {
2446
2446
  t.plan(2)
2447
2447
  const fastify = Fastify()
2448
- await fastify.register(compressPlugin, { customTypes: /x-user-header$/ })
2448
+ await fastify.register(compressPlugin, { customTypes: /x-user-header$/u })
2449
2449
 
2450
2450
  fastify.get('/', (request, reply) => {
2451
2451
  reply
@@ -1,9 +1,9 @@
1
1
  'use strict'
2
2
 
3
3
  const { test } = require('tap')
4
- const { createReadStream } = require('fs')
5
- const path = require('path')
6
- const zlib = require('zlib')
4
+ const { createReadStream } = require('node:fs')
5
+ const path = require('node:path')
6
+ const zlib = require('node:zlib')
7
7
  const pump = require('pump')
8
8
  const Fastify = require('fastify')
9
9
  const compressPlugin = require('../index')
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
3
  const { test } = require('tap')
4
- const { createReadStream, readFile, readFileSync } = require('fs')
5
- const zlib = require('zlib')
4
+ const { createReadStream, readFile, readFileSync } = require('node:fs')
5
+ const zlib = require('node:zlib')
6
6
  const Fastify = require('fastify')
7
7
  const compressPlugin = require('../index')
8
8
 
@@ -1,9 +1,9 @@
1
1
  'use strict'
2
2
 
3
3
  const { test } = require('tap')
4
- const { createReadStream } = require('fs')
5
- const path = require('path')
6
- const zlib = require('zlib')
4
+ const { createReadStream } = require('node:fs')
5
+ const path = require('node:path')
6
+ const zlib = require('node:zlib')
7
7
  const pump = require('pump')
8
8
  const Fastify = require('fastify')
9
9
  const compressPlugin = require('../index')
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
- const { createReadStream } = require('fs')
4
- const { Socket } = require('net')
5
- const { Duplex, PassThrough, Readable, Stream, Transform, Writable } = require('stream')
3
+ const { createReadStream } = require('node:fs')
4
+ const { Socket } = require('node:net')
5
+ const { Duplex, PassThrough, Readable, Stream, Transform, Writable } = require('node:stream')
6
6
  const { test } = require('tap')
7
7
  const { isStream, isDeflate, isGzip } = require('../lib/utils')
8
8