@fastify/compress 5.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/.github/dependabot.yml +13 -0
- package/.github/stale.yml +21 -0
- package/.github/workflows/ci.yml +47 -0
- package/.taprc +6 -0
- package/LICENSE +21 -0
- package/README.md +310 -0
- package/index.d.ts +81 -0
- package/index.js +556 -0
- package/lib/utils.js +7 -0
- package/package.json +73 -0
- package/test/global-compress.test.js +3048 -0
- package/test/global-decompress.test.js +423 -0
- package/test/routes-compress.test.js +437 -0
- package/test/routes-decompress.test.js +305 -0
- package/test/types/index.test-d.ts +115 -0
- package/test/utils.test.js +27 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('tap')
|
|
4
|
+
const { createReadStream } = require('fs')
|
|
5
|
+
const path = require('path')
|
|
6
|
+
const zlib = require('zlib')
|
|
7
|
+
const pump = require('pump')
|
|
8
|
+
const Fastify = require('fastify')
|
|
9
|
+
const compressPlugin = require('../index')
|
|
10
|
+
|
|
11
|
+
function createPayload (compressor) {
|
|
12
|
+
let payload = createReadStream(path.resolve(__dirname, '../package.json'))
|
|
13
|
+
|
|
14
|
+
if (compressor) {
|
|
15
|
+
payload = pump(payload, compressor())
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return payload
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
test('It should decompress the request payload :', async (t) => {
|
|
22
|
+
t.test('using brotli algorithm when `Content-Encoding` request header value is set to `br`', async (t) => {
|
|
23
|
+
t.plan(2)
|
|
24
|
+
|
|
25
|
+
const fastify = Fastify()
|
|
26
|
+
await fastify.register(compressPlugin)
|
|
27
|
+
|
|
28
|
+
fastify.post('/', (request, reply) => {
|
|
29
|
+
reply.send(request.body.name)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const response = await fastify.inject({
|
|
33
|
+
url: '/',
|
|
34
|
+
method: 'POST',
|
|
35
|
+
headers: {
|
|
36
|
+
'content-type': 'application/json',
|
|
37
|
+
'content-encoding': 'br'
|
|
38
|
+
},
|
|
39
|
+
payload: createPayload(zlib.createBrotliCompress)
|
|
40
|
+
})
|
|
41
|
+
t.equal(response.statusCode, 200)
|
|
42
|
+
t.equal(response.body, '@fastify/compress')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
t.test('using deflate algorithm when `Content-Encoding` request header value is set to `deflate`', async (t) => {
|
|
46
|
+
t.plan(2)
|
|
47
|
+
|
|
48
|
+
const fastify = Fastify()
|
|
49
|
+
await fastify.register(compressPlugin)
|
|
50
|
+
|
|
51
|
+
fastify.post('/', (request, reply) => {
|
|
52
|
+
reply.send(request.body.name)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const response = await fastify.inject({
|
|
56
|
+
url: '/',
|
|
57
|
+
method: 'POST',
|
|
58
|
+
headers: {
|
|
59
|
+
'content-type': 'application/json',
|
|
60
|
+
'content-encoding': 'deflate'
|
|
61
|
+
},
|
|
62
|
+
payload: createPayload(zlib.createDeflate)
|
|
63
|
+
})
|
|
64
|
+
t.equal(response.statusCode, 200)
|
|
65
|
+
t.equal(response.body, '@fastify/compress')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
t.test('using gzip algorithm when `Content-Encoding` request header value is set to `gzip`', async (t) => {
|
|
69
|
+
t.plan(2)
|
|
70
|
+
|
|
71
|
+
const fastify = Fastify()
|
|
72
|
+
await fastify.register(compressPlugin)
|
|
73
|
+
|
|
74
|
+
fastify.post('/', (request, reply) => {
|
|
75
|
+
reply.send(request.body.name)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
const response = await fastify.inject({
|
|
79
|
+
url: '/',
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: {
|
|
82
|
+
'content-type': 'application/json',
|
|
83
|
+
'content-encoding': 'gzip'
|
|
84
|
+
},
|
|
85
|
+
payload: createPayload(zlib.createGzip)
|
|
86
|
+
})
|
|
87
|
+
t.equal(response.statusCode, 200)
|
|
88
|
+
t.equal(response.body, '@fastify/compress')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
t.test('using the `forceRequestEncoding` provided algorithm over the `Content-Encoding` request header value', async (t) => {
|
|
92
|
+
t.plan(2)
|
|
93
|
+
|
|
94
|
+
const fastify = Fastify()
|
|
95
|
+
await fastify.register(compressPlugin, { forceRequestEncoding: 'gzip' })
|
|
96
|
+
|
|
97
|
+
fastify.post('/', (request, reply) => {
|
|
98
|
+
reply.send(request.body.name)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
const response = await fastify.inject({
|
|
102
|
+
url: '/',
|
|
103
|
+
method: 'POST',
|
|
104
|
+
headers: {
|
|
105
|
+
'content-type': 'application/json',
|
|
106
|
+
'content-encoding': 'deflate'
|
|
107
|
+
},
|
|
108
|
+
payload: createPayload(zlib.createGzip)
|
|
109
|
+
})
|
|
110
|
+
t.equal(response.statusCode, 200)
|
|
111
|
+
t.equal(response.body, '@fastify/compress')
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
test('It should not decompress :', async (t) => {
|
|
116
|
+
t.test('when `Content-Encoding` request header is missing', async (t) => {
|
|
117
|
+
t.plan(2)
|
|
118
|
+
|
|
119
|
+
const fastify = Fastify()
|
|
120
|
+
await fastify.register(compressPlugin)
|
|
121
|
+
|
|
122
|
+
fastify.post('/', (request, reply) => {
|
|
123
|
+
reply.send(request.body.name)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
const response = await fastify.inject({
|
|
127
|
+
url: '/',
|
|
128
|
+
method: 'POST',
|
|
129
|
+
headers: {
|
|
130
|
+
'content-type': 'application/json'
|
|
131
|
+
},
|
|
132
|
+
payload: createPayload()
|
|
133
|
+
})
|
|
134
|
+
t.equal(response.statusCode, 200)
|
|
135
|
+
t.equal(response.body, '@fastify/compress')
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
t.test('when `Content-Encoding` request header value is set to `identity`', async (t) => {
|
|
139
|
+
t.plan(2)
|
|
140
|
+
|
|
141
|
+
const fastify = Fastify()
|
|
142
|
+
await fastify.register(compressPlugin)
|
|
143
|
+
|
|
144
|
+
fastify.post('/', (request, reply) => {
|
|
145
|
+
reply.send(request.body.name)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
const response = await fastify.inject({
|
|
149
|
+
url: '/',
|
|
150
|
+
method: 'POST',
|
|
151
|
+
headers: {
|
|
152
|
+
'content-type': 'application/json',
|
|
153
|
+
'content-encoding': 'identity'
|
|
154
|
+
},
|
|
155
|
+
payload: createPayload()
|
|
156
|
+
})
|
|
157
|
+
t.equal(response.statusCode, 200)
|
|
158
|
+
t.equal(response.body, '@fastify/compress')
|
|
159
|
+
})
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
test('It should return an error :', async (t) => {
|
|
163
|
+
t.test('when `Content-Encoding` request header value is not supported', async (t) => {
|
|
164
|
+
t.plan(2)
|
|
165
|
+
|
|
166
|
+
const fastify = Fastify()
|
|
167
|
+
await fastify.register(compressPlugin)
|
|
168
|
+
|
|
169
|
+
fastify.post('/', (request, reply) => {
|
|
170
|
+
reply.send(request.body.name)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
const response = await fastify.inject({
|
|
174
|
+
url: '/',
|
|
175
|
+
method: 'POST',
|
|
176
|
+
headers: {
|
|
177
|
+
'content-type': 'application/json',
|
|
178
|
+
'content-encoding': 'whatever'
|
|
179
|
+
},
|
|
180
|
+
payload: createPayload(zlib.createDeflate)
|
|
181
|
+
})
|
|
182
|
+
t.equal(response.statusCode, 415)
|
|
183
|
+
t.strictSame(response.json(), {
|
|
184
|
+
statusCode: 415,
|
|
185
|
+
code: 'FST_CP_ERR_INVALID_CONTENT_ENCODING',
|
|
186
|
+
error: 'Unsupported Media Type',
|
|
187
|
+
message: 'Unsupported Content-Encoding: whatever'
|
|
188
|
+
})
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
t.test('when `Content-Encoding` request header value is disabled by the `requestEncodings` option', async (t) => {
|
|
192
|
+
t.plan(2)
|
|
193
|
+
|
|
194
|
+
const fastify = Fastify()
|
|
195
|
+
await fastify.register(compressPlugin, { requestEncodings: ['br'] })
|
|
196
|
+
|
|
197
|
+
fastify.post('/', (request, reply) => {
|
|
198
|
+
reply.send(request.body.name)
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
const response = await fastify.inject({
|
|
202
|
+
url: '/',
|
|
203
|
+
method: 'POST',
|
|
204
|
+
headers: {
|
|
205
|
+
'content-type': 'application/json',
|
|
206
|
+
'content-encoding': 'gzip'
|
|
207
|
+
},
|
|
208
|
+
payload: createPayload(zlib.createDeflate)
|
|
209
|
+
})
|
|
210
|
+
t.equal(response.statusCode, 415)
|
|
211
|
+
t.strictSame(response.json(), {
|
|
212
|
+
statusCode: 415,
|
|
213
|
+
code: 'FST_CP_ERR_INVALID_CONTENT_ENCODING',
|
|
214
|
+
error: 'Unsupported Media Type',
|
|
215
|
+
message: 'Unsupported Content-Encoding: gzip'
|
|
216
|
+
})
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
t.test('when the compressed payload is invalid according to `Content-Encoding` request header value', async (t) => {
|
|
220
|
+
t.plan(2)
|
|
221
|
+
|
|
222
|
+
const fastify = Fastify()
|
|
223
|
+
await fastify.register(compressPlugin)
|
|
224
|
+
|
|
225
|
+
fastify.post('/', (request, reply) => {
|
|
226
|
+
reply.send(request.body.name)
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
const response = await fastify.inject({
|
|
230
|
+
url: '/',
|
|
231
|
+
method: 'POST',
|
|
232
|
+
headers: {
|
|
233
|
+
'content-type': 'application/json',
|
|
234
|
+
'content-encoding': 'deflate'
|
|
235
|
+
},
|
|
236
|
+
payload: createPayload(zlib.createGzip)
|
|
237
|
+
})
|
|
238
|
+
t.equal(response.statusCode, 400)
|
|
239
|
+
t.strictSame(response.json(), {
|
|
240
|
+
statusCode: 400,
|
|
241
|
+
code: 'FST_CP_ERR_INVALID_CONTENT',
|
|
242
|
+
error: 'Bad Request',
|
|
243
|
+
message: 'Could not decompress the request payload using the provided encoding'
|
|
244
|
+
})
|
|
245
|
+
})
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
test('It should return the error returned by :', async (t) => {
|
|
249
|
+
t.test('`onUnsupportedRequestEncoding`', async (t) => {
|
|
250
|
+
t.plan(2)
|
|
251
|
+
|
|
252
|
+
const fastify = Fastify()
|
|
253
|
+
await fastify.register(compressPlugin, {
|
|
254
|
+
onUnsupportedRequestEncoding (encoding, request) {
|
|
255
|
+
return {
|
|
256
|
+
statusCode: 400,
|
|
257
|
+
code: 'INVALID',
|
|
258
|
+
error: 'Bad Request',
|
|
259
|
+
message: `We don't want to deal with ${encoding}.`
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
fastify.post('/', (request, reply) => {
|
|
265
|
+
reply.send(request.body.name)
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
const response = await fastify.inject({
|
|
269
|
+
url: '/',
|
|
270
|
+
method: 'POST',
|
|
271
|
+
headers: {
|
|
272
|
+
'content-type': 'application/json',
|
|
273
|
+
'content-encoding': 'whatever'
|
|
274
|
+
},
|
|
275
|
+
payload: createPayload(zlib.createDeflate)
|
|
276
|
+
})
|
|
277
|
+
t.equal(response.statusCode, 400)
|
|
278
|
+
t.strictSame(response.json(), {
|
|
279
|
+
statusCode: 400,
|
|
280
|
+
code: 'INVALID',
|
|
281
|
+
error: 'Bad Request',
|
|
282
|
+
message: 'We don\'t want to deal with whatever.'
|
|
283
|
+
})
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
t.test('`onInvalidRequestPayload`', async (t) => {
|
|
287
|
+
t.plan(2)
|
|
288
|
+
|
|
289
|
+
const fastify = Fastify()
|
|
290
|
+
await fastify.register(compressPlugin, {
|
|
291
|
+
onInvalidRequestPayload (encoding, request, error) {
|
|
292
|
+
return {
|
|
293
|
+
statusCode: 400,
|
|
294
|
+
code: 'INVALID',
|
|
295
|
+
error: 'Bad Request',
|
|
296
|
+
message: `What have you sent us? ${encoding} ${error.message}.`
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
fastify.post('/', (request, reply) => {
|
|
302
|
+
reply.send(request.body.name)
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
const response = await fastify.inject({
|
|
306
|
+
url: '/',
|
|
307
|
+
method: 'POST',
|
|
308
|
+
headers: {
|
|
309
|
+
'content-type': 'application/json',
|
|
310
|
+
'content-encoding': 'deflate'
|
|
311
|
+
},
|
|
312
|
+
payload: createPayload(zlib.createGzip)
|
|
313
|
+
})
|
|
314
|
+
t.equal(response.statusCode, 400)
|
|
315
|
+
t.strictSame(response.json(), {
|
|
316
|
+
statusCode: 400,
|
|
317
|
+
code: 'INVALID',
|
|
318
|
+
error: 'Bad Request',
|
|
319
|
+
message: 'What have you sent us? deflate incorrect header check.'
|
|
320
|
+
})
|
|
321
|
+
})
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
test('It should return the default error :', async (t) => {
|
|
325
|
+
t.test('when `onUnsupportedRequestEncoding` throws', async (t) => {
|
|
326
|
+
t.plan(2)
|
|
327
|
+
|
|
328
|
+
const fastify = Fastify()
|
|
329
|
+
await fastify.register(compressPlugin, {
|
|
330
|
+
onUnsupportedRequestEncoding (encoding, request) {
|
|
331
|
+
throw new Error('Kaboom!')
|
|
332
|
+
}
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
fastify.post('/', (request, reply) => {
|
|
336
|
+
reply.send(request.body.name)
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
const response = await fastify.inject({
|
|
340
|
+
url: '/',
|
|
341
|
+
method: 'POST',
|
|
342
|
+
headers: {
|
|
343
|
+
'content-type': 'application/json',
|
|
344
|
+
'content-encoding': 'whatever'
|
|
345
|
+
},
|
|
346
|
+
payload: createPayload(zlib.createDeflate)
|
|
347
|
+
})
|
|
348
|
+
t.equal(response.statusCode, 415)
|
|
349
|
+
t.strictSame(response.json(), {
|
|
350
|
+
statusCode: 415,
|
|
351
|
+
code: 'FST_CP_ERR_INVALID_CONTENT_ENCODING',
|
|
352
|
+
error: 'Unsupported Media Type',
|
|
353
|
+
message: 'Unsupported Content-Encoding: whatever'
|
|
354
|
+
})
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
t.test('when `onInvalidRequestPayload` throws', async (t) => {
|
|
358
|
+
t.plan(2)
|
|
359
|
+
|
|
360
|
+
const fastify = Fastify()
|
|
361
|
+
await fastify.register(compressPlugin, {
|
|
362
|
+
onInvalidRequestPayload (encoding, request, error) {
|
|
363
|
+
throw new Error('Kaboom!')
|
|
364
|
+
}
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
fastify.post('/', (request, reply) => {
|
|
368
|
+
reply.send(request.body.name)
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
const response = await fastify.inject({
|
|
372
|
+
url: '/',
|
|
373
|
+
method: 'POST',
|
|
374
|
+
headers: {
|
|
375
|
+
'content-type': 'application/json',
|
|
376
|
+
'content-encoding': 'deflate'
|
|
377
|
+
},
|
|
378
|
+
payload: createPayload(zlib.createGzip)
|
|
379
|
+
})
|
|
380
|
+
t.equal(response.statusCode, 400)
|
|
381
|
+
t.strictSame(response.json(), {
|
|
382
|
+
statusCode: 400,
|
|
383
|
+
code: 'FST_CP_ERR_INVALID_CONTENT',
|
|
384
|
+
error: 'Bad Request',
|
|
385
|
+
message: 'Could not decompress the request payload using the provided encoding'
|
|
386
|
+
})
|
|
387
|
+
})
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
test('It should validate `requestEncodings` option', (t) => {
|
|
391
|
+
t.plan(1)
|
|
392
|
+
|
|
393
|
+
const fastify = Fastify()
|
|
394
|
+
fastify.register(compressPlugin, { requestEncodings: [] })
|
|
395
|
+
|
|
396
|
+
fastify.ready((err) => {
|
|
397
|
+
t.equal(err.message, 'The `requestEncodings` option array must have at least 1 item.')
|
|
398
|
+
})
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
test('It should make sure that at least one encoding value is supported :', async (t) => {
|
|
402
|
+
t.test('when setting `requestEncodings`', (t) => {
|
|
403
|
+
t.plan(1)
|
|
404
|
+
|
|
405
|
+
const fastify = Fastify()
|
|
406
|
+
fastify.register(compressPlugin, { requestEncodings: ['whatever'] })
|
|
407
|
+
|
|
408
|
+
fastify.ready((err) => {
|
|
409
|
+
t.equal(err.message, 'None of the passed `requestEncodings` were supported — request decompression not possible.')
|
|
410
|
+
})
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
t.test('when setting `forceRequestEncodings`', (t) => {
|
|
414
|
+
t.plan(1)
|
|
415
|
+
|
|
416
|
+
const fastify = Fastify()
|
|
417
|
+
fastify.register(compressPlugin, { forceRequestEncoding: ['whatever'] })
|
|
418
|
+
|
|
419
|
+
fastify.ready((err) => {
|
|
420
|
+
t.equal(err.message, 'Unsupported decompression encoding whatever.')
|
|
421
|
+
})
|
|
422
|
+
})
|
|
423
|
+
})
|