@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 +2 -0
- package/.taprc +2 -6
- package/README.md +2 -2
- package/index.js +18 -10
- package/package.json +20 -22
- package/test/global-compress.test.js +10 -10
- package/test/global-decompress.test.js +3 -3
- package/test/routes-compress.test.js +2 -2
- package/test/routes-decompress.test.js +3 -3
- package/test/utils.test.js +3 -3
package/.gitattributes
ADDED
package/.taprc
CHANGED
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/@fastify/compress)
|
|
5
5
|
[](https://standardjs.com/)
|
|
6
6
|
|
|
7
|
-
Adds compression utils to [the Fastify `reply` object](https://
|
|
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
|
|
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
|
|
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
|
|
54
|
+
if (routeOptions.config?.compress !== undefined) {
|
|
54
55
|
routeOptions.compress = routeOptions.config.compress
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
// Manage compression options
|
|
58
|
-
if (
|
|
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
|
|
83
|
+
if (routeOptions.config?.decompress !== undefined) {
|
|
83
84
|
routeOptions.decompress = routeOptions.config.decompress
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
// Manage decompression options
|
|
87
|
-
if (
|
|
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)|(
|
|
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(
|
|
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": "
|
|
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.
|
|
9
|
-
"fastify-plugin": "^4.
|
|
9
|
+
"@fastify/accept-negotiator": "^1.1.0",
|
|
10
|
+
"fastify-plugin": "^4.5.0",
|
|
10
11
|
"into-stream": "^6.0.0",
|
|
11
|
-
"mime-db": "^1.
|
|
12
|
-
"minipass": "^
|
|
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.
|
|
20
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
21
|
-
"@typescript-eslint/parser": "^
|
|
22
|
-
"adm-zip": "^0.5.
|
|
23
|
-
"fastify": "^4.
|
|
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.
|
|
26
|
-
"tap": "^16.
|
|
27
|
-
"tsd": "^0.
|
|
28
|
-
"typescript": "^5.
|
|
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 -- --
|
|
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
|
|
36
|
-
"
|
|
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
|
|
40
|
-
"unit:
|
|
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')
|
package/test/utils.test.js
CHANGED
|
@@ -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
|
|