@fastify/compress 5.0.0 → 6.1.1
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/.github/workflows/ci.yml +9 -38
- package/README.md +43 -46
- package/index.js +12 -14
- package/lib/utils.js +32 -1
- package/package.json +9 -16
- package/test/global-compress.test.js +14 -12
- package/test/routes-compress.test.js +23 -37
- package/test/routes-decompress.test.js +21 -37
- package/test/utils.test.js +37 -1
package/.github/workflows/ci.yml
CHANGED
|
@@ -1,47 +1,18 @@
|
|
|
1
1
|
name: CI
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
on:
|
|
3
4
|
push:
|
|
4
5
|
paths-ignore:
|
|
5
|
-
- docs/**
|
|
6
|
+
- 'docs/**'
|
|
6
7
|
- '*.md'
|
|
7
8
|
pull_request:
|
|
8
9
|
paths-ignore:
|
|
9
|
-
- docs/**
|
|
10
|
+
- 'docs/**'
|
|
10
11
|
- '*.md'
|
|
12
|
+
|
|
11
13
|
jobs:
|
|
12
14
|
test:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- 10
|
|
18
|
-
- 12
|
|
19
|
-
- 14
|
|
20
|
-
- 16
|
|
21
|
-
- 17
|
|
22
|
-
os:
|
|
23
|
-
- macos-latest
|
|
24
|
-
- ubuntu-latest
|
|
25
|
-
- windows-latest
|
|
26
|
-
steps:
|
|
27
|
-
- uses: actions/checkout@v3
|
|
28
|
-
- name: Use Node.js
|
|
29
|
-
uses: actions/setup-node@v3
|
|
30
|
-
with:
|
|
31
|
-
node-version: ${{ matrix.node-version }}
|
|
32
|
-
- name: Install Dependencies
|
|
33
|
-
run: |
|
|
34
|
-
npm install --ignore-scripts
|
|
35
|
-
- name: Run Tests
|
|
36
|
-
run: |
|
|
37
|
-
npm test
|
|
38
|
-
automerge:
|
|
39
|
-
needs: test
|
|
40
|
-
runs-on: ubuntu-latest
|
|
41
|
-
permissions:
|
|
42
|
-
pull-requests: write
|
|
43
|
-
contents: write
|
|
44
|
-
steps:
|
|
45
|
-
- uses: fastify/github-action-merge-dependabot@v3
|
|
46
|
-
with:
|
|
47
|
-
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
15
|
+
uses: fastify/workflows/.github/workflows/plugins-ci.yml@v3
|
|
16
|
+
with:
|
|
17
|
+
license-check: true
|
|
18
|
+
lint: true
|
package/README.md
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
# fastify
|
|
1
|
+
# @fastify/compress
|
|
2
2
|
|
|
3
3
|

|
|
4
|
-
[](https://snyk.io/test/github/fastify/fastify-compress)
|
|
4
|
+
[](https://www.npmjs.com/package/@fastify/compress)
|
|
6
5
|
[](https://standardjs.com/)
|
|
7
6
|
|
|
8
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.
|
|
9
8
|
Supports `gzip`, `deflate`, and `brotli`.
|
|
10
9
|
|
|
11
|
-
> **Important note:** since
|
|
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.
|
|
12
11
|
|
|
13
12
|
## Install
|
|
14
13
|
```
|
|
15
|
-
npm i fastify
|
|
14
|
+
npm i @fastify/compress
|
|
16
15
|
```
|
|
17
16
|
|
|
18
17
|
## Usage - Compress replies
|
|
@@ -24,7 +23,7 @@ Currently, the following encoding tokens are supported, using the first acceptab
|
|
|
24
23
|
1. `br`
|
|
25
24
|
2. `gzip`
|
|
26
25
|
3. `deflate`
|
|
27
|
-
4. `*` (no preference —
|
|
26
|
+
4. `*` (no preference — `@fastify/compress` will use `gzip`)
|
|
28
27
|
5. `identity` (no compression)
|
|
29
28
|
|
|
30
29
|
If an unsupported encoding is received or if the `'accept-encoding'` header is missing, it will not compress the payload. If an unsupported encoding is received and you would like to return an error, provide an `onUnsupportedEncoding` option.
|
|
@@ -34,20 +33,20 @@ The plugin automatically decides if a payload should be compressed based on its
|
|
|
34
33
|
### Global hook
|
|
35
34
|
The global compression hook is enabled by default. To disable it, pass the option `{ global: false }`:
|
|
36
35
|
```javascript
|
|
37
|
-
fastify.register(
|
|
38
|
-
|
|
36
|
+
await fastify.register(
|
|
37
|
+
import('@fastify/compress'),
|
|
39
38
|
{ global: false }
|
|
40
39
|
)
|
|
41
40
|
```
|
|
42
41
|
Remember that thanks to the Fastify encapsulation model, you can set a global compression, but run it only in a subset of routes if you wrap them inside a plugin.
|
|
43
42
|
|
|
44
|
-
Important note! If you are using
|
|
43
|
+
Important note! If you are using `@fastify/compress` plugin together with `@fastify/static` plugin, you must register the `@fastify/compress` (with *global hook*) **before** registering `@fastify/static`.
|
|
45
44
|
|
|
46
45
|
### Per Route options
|
|
47
46
|
You can specify different options for compression per route by passing in the `compress` options on the route's configuration.
|
|
48
47
|
```javascript
|
|
49
|
-
fastify.register(
|
|
50
|
-
|
|
48
|
+
await fastify.register(
|
|
49
|
+
import('@fastify/compress'),
|
|
51
50
|
{ global: false }
|
|
52
51
|
)
|
|
53
52
|
|
|
@@ -74,21 +73,19 @@ Note that the compress method is configured with either the per route parameters
|
|
|
74
73
|
the plugin was defined as global.
|
|
75
74
|
|
|
76
75
|
```javascript
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
import fs from 'fs'
|
|
77
|
+
import fastify from 'fastify'
|
|
79
78
|
|
|
80
|
-
|
|
79
|
+
const app = fastify()
|
|
80
|
+
await app.register(import('@fastify/compress'), { global: false })
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
app.get('/', (req, reply) => {
|
|
83
83
|
reply
|
|
84
84
|
.type('text/plain')
|
|
85
85
|
.compress(fs.createReadStream('./package.json'))
|
|
86
86
|
})
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
if (err) throw err
|
|
90
|
-
console.log(`server listening on ${fastify.server.address().port}`)
|
|
91
|
-
})
|
|
88
|
+
await app.listen({ port: 3000 })
|
|
92
89
|
```
|
|
93
90
|
|
|
94
91
|
## Compress Options
|
|
@@ -96,16 +93,16 @@ fastify.listen(3000, function (err) {
|
|
|
96
93
|
### threshold
|
|
97
94
|
The minimum byte size for a response to be compressed. Defaults to `1024`.
|
|
98
95
|
```javascript
|
|
99
|
-
fastify.register(
|
|
100
|
-
|
|
96
|
+
await fastify.register(
|
|
97
|
+
import('@fastify/compress'),
|
|
101
98
|
{ threshold: 2048 }
|
|
102
99
|
)
|
|
103
100
|
```
|
|
104
101
|
### customTypes
|
|
105
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.
|
|
106
103
|
```javascript
|
|
107
|
-
fastify.register(
|
|
108
|
-
|
|
104
|
+
await fastify.register(
|
|
105
|
+
import('@fastify/compress'),
|
|
109
106
|
{ customTypes: /x-protobuf$/ }
|
|
110
107
|
)
|
|
111
108
|
```
|
|
@@ -113,8 +110,8 @@ fastify.register(
|
|
|
113
110
|
### onUnsupportedEncoding
|
|
114
111
|
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.
|
|
115
112
|
```javascript
|
|
116
|
-
fastify.register(
|
|
117
|
-
|
|
113
|
+
await fastify.register(
|
|
114
|
+
import('@fastify/compress'),
|
|
118
115
|
{
|
|
119
116
|
onUnsupportedEncoding: (encoding, request, reply) => {
|
|
120
117
|
reply.code(406)
|
|
@@ -130,8 +127,8 @@ You can selectively disable response compression by using the `x-no-compression`
|
|
|
130
127
|
### Inflate pre-compressed bodies for clients that do not support compression
|
|
131
128
|
Optional feature to inflate pre-compressed data if the client does not include one of the supported compression types in its `accept-encoding` header.
|
|
132
129
|
```javascript
|
|
133
|
-
fastify.register(
|
|
134
|
-
|
|
130
|
+
await fastify.register(
|
|
131
|
+
import('@fastify/compress'),
|
|
135
132
|
{ inflateIfDeflated: true }
|
|
136
133
|
)
|
|
137
134
|
|
|
@@ -143,11 +140,11 @@ fastify.get('/file', (req, reply) =>
|
|
|
143
140
|
|
|
144
141
|
### Customize encoding priority
|
|
145
142
|
|
|
146
|
-
By default,
|
|
143
|
+
By default, `@fastify/compress` prioritizes compression as described [at the beginning of §Usage - Compress replies](#usage). You can change that by passing an array of compression tokens to the `encodings` option:
|
|
147
144
|
|
|
148
145
|
```javascript
|
|
149
|
-
fastify.register(
|
|
150
|
-
|
|
146
|
+
await fastify.register(
|
|
147
|
+
import('@fastify/compress'),
|
|
151
148
|
// Only support gzip and deflate, and prefer deflate to gzip
|
|
152
149
|
{ encodings: ['deflate', 'gzip'] }
|
|
153
150
|
)
|
|
@@ -166,17 +163,17 @@ You can tune compression by setting the `brotliOptions` and `zlibOptions` proper
|
|
|
166
163
|
},
|
|
167
164
|
},
|
|
168
165
|
zlibOptions: {
|
|
169
|
-
level:
|
|
166
|
+
level: 6, // default is typically 6, max is 9, min is 0
|
|
170
167
|
}
|
|
171
168
|
});
|
|
172
169
|
```
|
|
173
170
|
|
|
174
171
|
### Manage `Content-Length` header removal with removeContentLengthHeader
|
|
175
|
-
By default,
|
|
172
|
+
By default, `@fastify/compress` removes the reply `Content-Length` header. You can change that by setting the `removeContentLengthHeader` to `false` either on a global scope or on a route specific scope.
|
|
176
173
|
|
|
177
174
|
```javascript
|
|
178
175
|
// Global plugin scope
|
|
179
|
-
server.register(fastifyCompress, { global: true, removeContentLengthHeader: false });
|
|
176
|
+
await server.register(fastifyCompress, { global: true, removeContentLengthHeader: false });
|
|
180
177
|
|
|
181
178
|
// Route specific scope
|
|
182
179
|
fastify.get('/file', {
|
|
@@ -204,8 +201,8 @@ If the request header is missing, the plugin will not do anything and yield to t
|
|
|
204
201
|
|
|
205
202
|
The global request decompression hook is enabled by default. To disable it, pass the option `{ global: false }`:
|
|
206
203
|
```javascript
|
|
207
|
-
fastify.register(
|
|
208
|
-
|
|
204
|
+
await fastify.register(
|
|
205
|
+
import('@fastify/compress'),
|
|
209
206
|
{ global: false }
|
|
210
207
|
)
|
|
211
208
|
```
|
|
@@ -216,8 +213,8 @@ Remember that thanks to the Fastify encapsulation model, you can set a global de
|
|
|
216
213
|
|
|
217
214
|
You can specify different options for decompression per route by passing in the `decompress` options on the route's configuration.
|
|
218
215
|
```javascript
|
|
219
|
-
fastify.register(
|
|
220
|
-
|
|
216
|
+
await fastify.register(
|
|
217
|
+
import('@fastify/compress'),
|
|
221
218
|
{ global: false }
|
|
222
219
|
)
|
|
223
220
|
|
|
@@ -238,11 +235,11 @@ fastify.get('/custom-route', {
|
|
|
238
235
|
|
|
239
236
|
### requestEncodings
|
|
240
237
|
|
|
241
|
-
By default,
|
|
238
|
+
By default, `@fastify/compress` accepts all encodings specified [at the beginning of §Usage - Decompress request payloads](#usage). You can change that by passing an array of compression tokens to the `requestEncodings` option:
|
|
242
239
|
|
|
243
240
|
```javascript
|
|
244
|
-
fastify.register(
|
|
245
|
-
|
|
241
|
+
await fastify.register(
|
|
242
|
+
import('@fastify/compress'),
|
|
246
243
|
// Only support gzip
|
|
247
244
|
{ requestEncodings: ['gzip'] }
|
|
248
245
|
)
|
|
@@ -250,19 +247,19 @@ fastify.register(
|
|
|
250
247
|
|
|
251
248
|
### forceRequestEncoding
|
|
252
249
|
|
|
253
|
-
By default,
|
|
250
|
+
By default, `@fastify/compress` chooses the decompressing algorithm by looking at the `content-encoding` header, if present.
|
|
254
251
|
|
|
255
252
|
You can force one algorithm and ignore the header at all by providing the `forceRequestEncoding` option.
|
|
256
253
|
|
|
257
|
-
Note that if the request payload is not compressed,
|
|
254
|
+
Note that if the request payload is not compressed, `@fastify/compress` will try to decompress, resulting in an error.
|
|
258
255
|
|
|
259
256
|
### onUnsupportedRequestEncoding
|
|
260
257
|
|
|
261
258
|
When the request payload encoding is not supported, you can customize the response error by setting the `onUnsupportedEncoding(request, encoding)` option to be a function that returns an error.
|
|
262
259
|
|
|
263
260
|
```javascript
|
|
264
|
-
fastify.register(
|
|
265
|
-
|
|
261
|
+
await fastify.register(
|
|
262
|
+
import('@fastify/compress'),
|
|
266
263
|
{
|
|
267
264
|
onUnsupportedRequestEncoding: (request, encoding) => {
|
|
268
265
|
return {
|
|
@@ -281,8 +278,8 @@ fastify.register(
|
|
|
281
278
|
When the request payload cannot be decompressed using the detected algorithm, you can customize the response error setting the `onInvalidRequestPayload(request, encoding)` option to be a function that returns an error.
|
|
282
279
|
|
|
283
280
|
```javascript
|
|
284
|
-
fastify.register(
|
|
285
|
-
|
|
281
|
+
await fastify.register(
|
|
282
|
+
import('@fastify/compress'),
|
|
286
283
|
{
|
|
287
284
|
onInvalidRequestPayload: (request, encoding, error) => {
|
|
288
285
|
return {
|
package/index.js
CHANGED
|
@@ -8,12 +8,10 @@ const intoStream = require('into-stream')
|
|
|
8
8
|
const peek = require('peek-stream')
|
|
9
9
|
const Minipass = require('minipass')
|
|
10
10
|
const pumpify = require('pumpify')
|
|
11
|
-
const
|
|
12
|
-
const isDeflate = require('is-deflate')
|
|
13
|
-
const encodingNegotiator = require('encoding-negotiator')
|
|
11
|
+
const encodingNegotiator = require('@fastify/accept-negotiator')
|
|
14
12
|
const { inherits, format } = require('util')
|
|
15
13
|
|
|
16
|
-
const { isStream } = require('./lib/utils')
|
|
14
|
+
const { isStream, isGzip, isDeflate } = require('./lib/utils')
|
|
17
15
|
|
|
18
16
|
const InvalidRequestEncodingError = createError('FST_CP_ERR_INVALID_CONTENT_ENCODING', 'Unsupported Content-Encoding: %s', 415)
|
|
19
17
|
const InvalidRequestCompressedPayloadError = createError('FST_CP_ERR_INVALID_CONTENT', 'Could not decompress the request payload using the provided encoding', 400)
|
|
@@ -143,8 +141,8 @@ function processCompressParams (opts) {
|
|
|
143
141
|
|
|
144
142
|
params.encodings = Array.isArray(opts.encodings)
|
|
145
143
|
? supportedEncodings
|
|
146
|
-
|
|
147
|
-
|
|
144
|
+
.filter(encoding => opts.encodings.includes(encoding))
|
|
145
|
+
.sort((a, b) => opts.encodings.indexOf(a) - supportedEncodings.indexOf(b))
|
|
148
146
|
: supportedEncodings
|
|
149
147
|
|
|
150
148
|
return params
|
|
@@ -175,8 +173,8 @@ function processDecompressParams (opts) {
|
|
|
175
173
|
|
|
176
174
|
params.encodings = Array.isArray(opts.requestEncodings)
|
|
177
175
|
? supportedEncodings
|
|
178
|
-
|
|
179
|
-
|
|
176
|
+
.filter(encoding => opts.requestEncodings.includes(encoding))
|
|
177
|
+
.sort((a, b) => opts.requestEncodings.indexOf(a) - supportedEncodings.indexOf(b))
|
|
180
178
|
: supportedEncodings
|
|
181
179
|
|
|
182
180
|
if (opts.forceRequestEncoding) {
|
|
@@ -268,8 +266,8 @@ function buildRouteCompress (fastify, params, routeOptions, decorateOnly) {
|
|
|
268
266
|
|
|
269
267
|
params.removeContentLengthHeader
|
|
270
268
|
? reply
|
|
271
|
-
|
|
272
|
-
|
|
269
|
+
.header('Content-Encoding', encoding)
|
|
270
|
+
.removeHeader('content-length')
|
|
273
271
|
: reply.header('Content-Encoding', encoding)
|
|
274
272
|
|
|
275
273
|
stream = zipStream(params.compressStream, encoding)
|
|
@@ -393,8 +391,8 @@ function compress (params) {
|
|
|
393
391
|
|
|
394
392
|
params.removeContentLengthHeader
|
|
395
393
|
? this
|
|
396
|
-
|
|
397
|
-
|
|
394
|
+
.header('Content-Encoding', encoding)
|
|
395
|
+
.removeHeader('content-length')
|
|
398
396
|
: this.header('Content-Encoding', encoding)
|
|
399
397
|
|
|
400
398
|
stream = zipStream(params.compressStream, encoding)
|
|
@@ -551,6 +549,6 @@ function createError (code, message, statusCode) {
|
|
|
551
549
|
}
|
|
552
550
|
|
|
553
551
|
module.exports = fp(compressPlugin, {
|
|
554
|
-
fastify: '
|
|
555
|
-
name: 'fastify
|
|
552
|
+
fastify: '4.x',
|
|
553
|
+
name: '@fastify/compress'
|
|
556
554
|
})
|
package/lib/utils.js
CHANGED
|
@@ -1,7 +1,38 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
// https://datatracker.ietf.org/doc/html/rfc1950#section-2
|
|
4
|
+
function isDeflate (buffer) {
|
|
5
|
+
return (
|
|
6
|
+
typeof buffer === 'object' &&
|
|
7
|
+
buffer !== null &&
|
|
8
|
+
buffer.length > 1 &&
|
|
9
|
+
// CM = 8 denotes the "deflate" compression method
|
|
10
|
+
(buffer[0] & 0x0f) === 0x08 &&
|
|
11
|
+
// CINFO Values of above 7 are not allowed by RFC 1950
|
|
12
|
+
(buffer[0] & 0x80) === 0 &&
|
|
13
|
+
// The FCHECK value must be such that CMF and FLG, when viewed as
|
|
14
|
+
// a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG),
|
|
15
|
+
// is a multiple of 31.
|
|
16
|
+
(((buffer[0] << 8) + buffer[1]) % 31) === 0
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// https://datatracker.ietf.org/doc/html/rfc1952#page-6
|
|
21
|
+
function isGzip (buffer) {
|
|
22
|
+
return (
|
|
23
|
+
typeof buffer === 'object' &&
|
|
24
|
+
buffer !== null &&
|
|
25
|
+
buffer.length > 2 &&
|
|
26
|
+
// ID1
|
|
27
|
+
buffer[0] === 0x1f &&
|
|
28
|
+
// ID2
|
|
29
|
+
buffer[1] === 0x8b &&
|
|
30
|
+
buffer[2] === 0x08
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
3
34
|
function isStream (stream) {
|
|
4
35
|
return stream !== null && typeof stream === 'object' && typeof stream.pipe === 'function'
|
|
5
36
|
}
|
|
6
37
|
|
|
7
|
-
module.exports = { isStream }
|
|
38
|
+
module.exports = { isGzip, isDeflate, isStream }
|
package/package.json
CHANGED
|
@@ -1,34 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fastify/compress",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"description": "Fastify compression utils",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"
|
|
9
|
-
"fastify-plugin": "^
|
|
8
|
+
"@fastify/accept-negotiator": "^1.0.0",
|
|
9
|
+
"fastify-plugin": "^4.0.0",
|
|
10
10
|
"into-stream": "^6.0.0",
|
|
11
|
-
"is-deflate": "^1.0.0",
|
|
12
|
-
"is-gzip": "^2.0.0",
|
|
13
|
-
"is-zip": "^1.0.0",
|
|
14
11
|
"mime-db": "^1.51.0",
|
|
15
12
|
"minipass": "^3.1.6",
|
|
16
13
|
"peek-stream": "^1.1.3",
|
|
17
14
|
"pump": "^3.0.0",
|
|
18
|
-
"pumpify": "^2.0.1"
|
|
19
|
-
"string-to-stream": "^3.0.1"
|
|
15
|
+
"pumpify": "^2.0.1"
|
|
20
16
|
},
|
|
21
17
|
"devDependencies": {
|
|
22
|
-
"@
|
|
18
|
+
"@fastify/pre-commit": "^2.0.2",
|
|
19
|
+
"@types/node": "^18.0.0",
|
|
23
20
|
"@typescript-eslint/eslint-plugin": "^5.9.0",
|
|
24
21
|
"@typescript-eslint/parser": "^5.9.0",
|
|
25
22
|
"adm-zip": "^0.5.9",
|
|
26
|
-
"fastify": "^
|
|
23
|
+
"fastify": "^4.0.0-rc.2",
|
|
27
24
|
"jsonstream": "^1.0.3",
|
|
28
|
-
"
|
|
29
|
-
"standard": "^16.0.4",
|
|
25
|
+
"standard": "^17.0.0",
|
|
30
26
|
"tap": "^16.0.0",
|
|
31
|
-
"tsd": "^0.
|
|
27
|
+
"tsd": "^0.22.0",
|
|
32
28
|
"typescript": "^4.5.4"
|
|
33
29
|
},
|
|
34
30
|
"scripts": {
|
|
@@ -61,9 +57,6 @@
|
|
|
61
57
|
"type": "git",
|
|
62
58
|
"url": "git+https://github.com/fastify/fastify-compress.git"
|
|
63
59
|
},
|
|
64
|
-
"engines": {
|
|
65
|
-
"node": ">=10.16"
|
|
66
|
-
},
|
|
67
60
|
"tsd": {
|
|
68
61
|
"directory": "test/types"
|
|
69
62
|
},
|
|
@@ -8,6 +8,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
12
|
|
|
12
13
|
test('When `global` is not set, it is `true` by default :', async (t) => {
|
|
13
14
|
t.test('it should compress Buffer data using brotli when `Accept-Encoding` request header is `br`', async (t) => {
|
|
@@ -343,7 +344,7 @@ test('It should send compressed Buffer data when `global` is `true` :', async (t
|
|
|
343
344
|
t.plan(1)
|
|
344
345
|
|
|
345
346
|
const fastify = Fastify()
|
|
346
|
-
fastify.register(compressPlugin, { global: true, threshold: 0 })
|
|
347
|
+
await fastify.register(compressPlugin, { global: true, threshold: 0 })
|
|
347
348
|
|
|
348
349
|
const buf = Buffer.from('hello world')
|
|
349
350
|
fastify.get('/', (request, reply) => {
|
|
@@ -1639,14 +1640,16 @@ test('It should return a serialized payload when `inflateIfDeflated` is `true` a
|
|
|
1639
1640
|
t.equal(two.payload, compressedBufferPayload.toString())
|
|
1640
1641
|
})
|
|
1641
1642
|
|
|
1642
|
-
test('It should close the stream', (t) => {
|
|
1643
|
-
t.plan(
|
|
1643
|
+
test('It should close the stream', async (t) => {
|
|
1644
|
+
t.plan(3)
|
|
1644
1645
|
|
|
1645
1646
|
const fastify = Fastify()
|
|
1646
|
-
fastify.register(compressPlugin, { global: true })
|
|
1647
|
+
await fastify.register(compressPlugin, { global: true })
|
|
1648
|
+
|
|
1649
|
+
const stream = createReadStream('./package.json')
|
|
1650
|
+
const closed = once(stream, 'close')
|
|
1647
1651
|
|
|
1648
1652
|
fastify.get('/', (request, reply) => {
|
|
1649
|
-
const stream = createReadStream('./package.json')
|
|
1650
1653
|
stream.on('close', () => t.ok('stream closed'))
|
|
1651
1654
|
|
|
1652
1655
|
reply
|
|
@@ -1654,16 +1657,15 @@ test('It should close the stream', (t) => {
|
|
|
1654
1657
|
.compress(stream)
|
|
1655
1658
|
})
|
|
1656
1659
|
|
|
1657
|
-
fastify.inject({
|
|
1660
|
+
const response = await fastify.inject({
|
|
1658
1661
|
url: '/',
|
|
1659
1662
|
method: 'GET'
|
|
1660
|
-
}, (err, response) => {
|
|
1661
|
-
t.error(err)
|
|
1662
|
-
|
|
1663
|
-
const file = readFileSync('./package.json', 'utf8')
|
|
1664
|
-
t.equal(response.statusCode, 200)
|
|
1665
|
-
t.equal(file, response.payload)
|
|
1666
1663
|
})
|
|
1664
|
+
|
|
1665
|
+
const file = readFileSync('./package.json', 'utf8')
|
|
1666
|
+
t.equal(response.statusCode, 200)
|
|
1667
|
+
t.equal(file, response.payload)
|
|
1668
|
+
await closed
|
|
1667
1669
|
})
|
|
1668
1670
|
|
|
1669
1671
|
test('It should log an existing error with stream onEnd handler', async (t) => {
|
|
@@ -225,27 +225,20 @@ test('When using routes `compress` settings :', async (t) => {
|
|
|
225
225
|
})
|
|
226
226
|
|
|
227
227
|
t.test('it should throw an error on invalid route `compress` settings', async (t) => {
|
|
228
|
-
t.plan(
|
|
228
|
+
t.plan(1)
|
|
229
229
|
|
|
230
230
|
const fastify = Fastify()
|
|
231
231
|
await fastify.register(compressPlugin, { global: false })
|
|
232
232
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
reply
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
url: '/',
|
|
241
|
-
method: 'GET',
|
|
242
|
-
headers: {
|
|
243
|
-
'accept-encoding': 'gzip'
|
|
244
|
-
}
|
|
245
|
-
}).catch((err) => {
|
|
246
|
-
t.type(err, Error)
|
|
233
|
+
try {
|
|
234
|
+
fastify.get('/', {
|
|
235
|
+
compress: 'bad config'
|
|
236
|
+
}, (request, reply) => {
|
|
237
|
+
reply.send('')
|
|
238
|
+
})
|
|
239
|
+
} catch (err) {
|
|
247
240
|
t.equal(err.message, 'Unknown value for route compress configuration')
|
|
248
|
-
}
|
|
241
|
+
}
|
|
249
242
|
})
|
|
250
243
|
})
|
|
251
244
|
|
|
@@ -385,32 +378,25 @@ test('When using the old routes `{ config: compress }` option :', async (t) => {
|
|
|
385
378
|
})
|
|
386
379
|
|
|
387
380
|
t.test('it should use the old routes `{ config: compress }` options over routes `compress` options', async (t) => {
|
|
388
|
-
t.plan(
|
|
381
|
+
t.plan(1)
|
|
389
382
|
|
|
390
383
|
const fastify = Fastify()
|
|
391
384
|
await fastify.register(compressPlugin, { global: false })
|
|
392
385
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
reply
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
url: '/',
|
|
406
|
-
method: 'GET',
|
|
407
|
-
headers: {
|
|
408
|
-
'accept-encoding': 'gzip'
|
|
409
|
-
}
|
|
410
|
-
}).catch((err) => {
|
|
411
|
-
t.type(err, Error)
|
|
386
|
+
try {
|
|
387
|
+
fastify.get('/', {
|
|
388
|
+
compress: {
|
|
389
|
+
zlib: { createGzip: () => zlib.createGzip() }
|
|
390
|
+
},
|
|
391
|
+
config: {
|
|
392
|
+
compress: 'bad config'
|
|
393
|
+
}
|
|
394
|
+
}, (request, reply) => {
|
|
395
|
+
reply.send('')
|
|
396
|
+
})
|
|
397
|
+
} catch (err) {
|
|
412
398
|
t.equal(err.message, 'Unknown value for route compress configuration')
|
|
413
|
-
}
|
|
399
|
+
}
|
|
414
400
|
})
|
|
415
401
|
})
|
|
416
402
|
|
|
@@ -189,26 +189,18 @@ test('When using routes `decompress` settings :', async (t) => {
|
|
|
189
189
|
})
|
|
190
190
|
|
|
191
191
|
t.test('it should throw an error on invalid route `decompress` settings', async (t) => {
|
|
192
|
-
t.plan(
|
|
192
|
+
t.plan(1)
|
|
193
193
|
|
|
194
194
|
const fastify = Fastify()
|
|
195
195
|
await fastify.register(compressPlugin, { global: false })
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
url: '/',
|
|
203
|
-
method: 'POST',
|
|
204
|
-
headers: {
|
|
205
|
-
'content-encoding': 'gzip'
|
|
206
|
-
},
|
|
207
|
-
payload: ''
|
|
208
|
-
}).catch((err) => {
|
|
209
|
-
t.type(err, Error)
|
|
197
|
+
try {
|
|
198
|
+
fastify.post('/', { decompress: 'bad config' }, (request, reply) => {
|
|
199
|
+
reply.send(request.body.name)
|
|
200
|
+
})
|
|
201
|
+
} catch (err) {
|
|
210
202
|
t.equal(err.message, 'Unknown value for route decompress configuration')
|
|
211
|
-
}
|
|
203
|
+
}
|
|
212
204
|
})
|
|
213
205
|
})
|
|
214
206
|
|
|
@@ -274,32 +266,24 @@ test('When using the old routes `{ config: decompress }` option :', async (t) =>
|
|
|
274
266
|
})
|
|
275
267
|
|
|
276
268
|
t.test('it should use the old routes `{ config: decompress }` options over routes `decompress` options', async (t) => {
|
|
277
|
-
t.plan(
|
|
269
|
+
t.plan(1)
|
|
278
270
|
|
|
279
271
|
const fastify = Fastify()
|
|
280
272
|
await fastify.register(compressPlugin, { global: false })
|
|
281
273
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
url: '/',
|
|
295
|
-
method: 'POST',
|
|
296
|
-
headers: {
|
|
297
|
-
'content-encoding': 'gzip'
|
|
298
|
-
},
|
|
299
|
-
payload: ''
|
|
300
|
-
}).catch((err) => {
|
|
301
|
-
t.type(err, Error)
|
|
274
|
+
try {
|
|
275
|
+
fastify.post('/', {
|
|
276
|
+
decompress: {
|
|
277
|
+
zlib: { createGunzip: () => zlib.createGunzip() }
|
|
278
|
+
},
|
|
279
|
+
config: {
|
|
280
|
+
decompress: 'bad config'
|
|
281
|
+
}
|
|
282
|
+
}, (request, reply) => {
|
|
283
|
+
reply.send(request.body.name)
|
|
284
|
+
})
|
|
285
|
+
} catch (err) {
|
|
302
286
|
t.equal(err.message, 'Unknown value for route decompress configuration')
|
|
303
|
-
}
|
|
287
|
+
}
|
|
304
288
|
})
|
|
305
289
|
})
|
package/test/utils.test.js
CHANGED
|
@@ -4,7 +4,7 @@ const { createReadStream } = require('fs')
|
|
|
4
4
|
const { Socket } = require('net')
|
|
5
5
|
const { Duplex, PassThrough, Readable, Stream, Transform, Writable } = require('stream')
|
|
6
6
|
const { test } = require('tap')
|
|
7
|
-
const { isStream } = require('../lib/utils')
|
|
7
|
+
const { isStream, isDeflate, isGzip } = require('../lib/utils')
|
|
8
8
|
|
|
9
9
|
test('isStream() utility should be able to detect Streams', async (t) => {
|
|
10
10
|
t.plan(12)
|
|
@@ -25,3 +25,39 @@ test('isStream() utility should be able to detect Streams', async (t) => {
|
|
|
25
25
|
t.equal(isStream(undefined), false)
|
|
26
26
|
t.equal(isStream(''), false)
|
|
27
27
|
})
|
|
28
|
+
|
|
29
|
+
test('isDeflate() utility should be able to detect deflate compressed Buffer', async (t) => {
|
|
30
|
+
t.plan(14)
|
|
31
|
+
|
|
32
|
+
t.equal(isDeflate(Buffer.alloc(0)), false)
|
|
33
|
+
t.equal(isDeflate(Buffer.alloc(0)), false)
|
|
34
|
+
t.equal(isDeflate(Buffer.from([0x78])), false)
|
|
35
|
+
t.equal(isDeflate(Buffer.from([0x78, 0x00])), false)
|
|
36
|
+
t.equal(isDeflate(Buffer.from([0x7a, 0x01])), false)
|
|
37
|
+
t.equal(isDeflate(Buffer.from([0x88, 0x01])), false)
|
|
38
|
+
t.equal(isDeflate(Buffer.from([0x78, 0x11])), false)
|
|
39
|
+
t.equal(isDeflate(Buffer.from([0x78, 0x01])), true)
|
|
40
|
+
t.equal(isDeflate(Buffer.from([0x78, 0x9c])), true)
|
|
41
|
+
t.equal(isDeflate(Buffer.from([0x78, 0xda])), true)
|
|
42
|
+
|
|
43
|
+
t.equal(isDeflate({}), false)
|
|
44
|
+
t.equal(isDeflate(null), false)
|
|
45
|
+
t.equal(isDeflate(undefined), false)
|
|
46
|
+
t.equal(isDeflate(''), false)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
test('isGzip() utility should be able to detect gzip compressed Buffer', async (t) => {
|
|
50
|
+
t.plan(10)
|
|
51
|
+
|
|
52
|
+
t.equal(isGzip(Buffer.alloc(0)), false)
|
|
53
|
+
t.equal(isGzip(Buffer.alloc(1)), false)
|
|
54
|
+
t.equal(isGzip(Buffer.alloc(2)), false)
|
|
55
|
+
t.equal(isGzip(Buffer.from([0x1f, 0x8b])), false)
|
|
56
|
+
t.equal(isGzip(Buffer.from([0x1f, 0x8b, 0x00])), false)
|
|
57
|
+
t.equal(isGzip(Buffer.from([0x1f, 0x8b, 0x08])), true)
|
|
58
|
+
|
|
59
|
+
t.equal(isGzip({}), false)
|
|
60
|
+
t.equal(isGzip(null), false)
|
|
61
|
+
t.equal(isGzip(undefined), false)
|
|
62
|
+
t.equal(isGzip(''), false)
|
|
63
|
+
})
|