@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.
@@ -0,0 +1,437 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('tap')
4
+ const { createReadStream, readFile, readFileSync } = require('fs')
5
+ const zlib = require('zlib')
6
+ const Fastify = require('fastify')
7
+ const compressPlugin = require('../index')
8
+
9
+ test('When using routes `compress` settings :', async (t) => {
10
+ t.test('it should compress data using the route custom provided `createDeflate` method', async (t) => {
11
+ t.plan(10)
12
+
13
+ let usedCustomGlobal = false
14
+ let usedCustom = false
15
+ const customZlibGlobal = { createDeflate: () => (usedCustomGlobal = true) && zlib.createDeflate() }
16
+ const customZlib = { createDeflate: () => (usedCustom = true) && zlib.createDeflate() }
17
+
18
+ const fastify = Fastify()
19
+ await fastify.register(compressPlugin, { global: true, zlib: customZlibGlobal })
20
+
21
+ fastify.get('/', (request, reply) => {
22
+ reply
23
+ .type('text/plain')
24
+ .compress(createReadStream('./package.json'))
25
+ })
26
+
27
+ fastify.get('/custom', {
28
+ compress: { zlib: customZlib }
29
+ }, (request, reply) => {
30
+ reply
31
+ .type('text/plain')
32
+ .compress(createReadStream('./package.json'))
33
+ })
34
+
35
+ await fastify.inject({
36
+ url: '/',
37
+ method: 'GET',
38
+ headers: {
39
+ 'accept-encoding': 'deflate'
40
+ }
41
+ }).then((response) => {
42
+ t.equal(usedCustom, false)
43
+ t.equal(usedCustomGlobal, true)
44
+
45
+ const file = readFileSync('./package.json', 'utf8')
46
+ const payload = zlib.inflateSync(response.rawPayload)
47
+ t.equal(response.headers['content-encoding'], 'deflate')
48
+ t.notOk(response.headers['content-length'], 'no content length')
49
+ t.equal(payload.toString('utf-8'), file)
50
+
51
+ usedCustom = false
52
+ usedCustomGlobal = false
53
+ })
54
+
55
+ const response = await fastify.inject({
56
+ url: '/custom',
57
+ method: 'GET',
58
+ headers: {
59
+ 'accept-encoding': 'deflate'
60
+ }
61
+ })
62
+ t.equal(usedCustom, true)
63
+ t.equal(usedCustomGlobal, false)
64
+
65
+ const file = readFileSync('./package.json', 'utf8')
66
+ const payload = zlib.inflateSync(response.rawPayload)
67
+ t.equal(response.headers['content-encoding'], 'deflate')
68
+ t.notOk(response.headers['content-length'], 'no content length')
69
+ t.equal(payload.toString('utf-8'), file)
70
+ })
71
+
72
+ t.test('it should compress data using the route custom provided `createGzip` method', async (t) => {
73
+ t.plan(8)
74
+
75
+ let usedCustomGlobal = false
76
+ let usedCustom = false
77
+ const customZlibGlobal = { createGzip: () => (usedCustomGlobal = true) && zlib.createGzip() }
78
+ const customZlib = { createGzip: () => (usedCustom = true) && zlib.createGzip() }
79
+
80
+ const fastify = Fastify()
81
+ await fastify.register(compressPlugin, { global: false, zlib: customZlibGlobal })
82
+
83
+ fastify.get('/', (request, reply) => {
84
+ reply
85
+ .type('text/plain')
86
+ .compress(createReadStream('./package.json'))
87
+ })
88
+
89
+ fastify.get('/custom', { compress: { zlib: customZlib } }, (request, reply) => {
90
+ reply
91
+ .type('text/plain')
92
+ .compress(createReadStream('./package.json'))
93
+ })
94
+
95
+ await fastify.inject({
96
+ url: '/',
97
+ method: 'GET',
98
+ headers: {
99
+ 'accept-encoding': 'gzip'
100
+ }
101
+ }).then((response) => {
102
+ t.equal(usedCustom, false)
103
+ t.equal(usedCustomGlobal, true)
104
+
105
+ const file = readFileSync('./package.json', 'utf8')
106
+ const payload = zlib.gunzipSync(response.rawPayload)
107
+ t.equal(response.headers['content-encoding'], 'gzip')
108
+ t.equal(payload.toString('utf-8'), file)
109
+
110
+ usedCustom = false
111
+ usedCustomGlobal = false
112
+ })
113
+
114
+ const response = await fastify.inject({
115
+ url: '/custom',
116
+ method: 'GET',
117
+ headers: {
118
+ 'accept-encoding': 'gzip'
119
+ }
120
+ })
121
+ t.equal(usedCustom, true)
122
+ t.equal(usedCustomGlobal, false)
123
+
124
+ const file = readFileSync('./package.json', 'utf8')
125
+ const payload = zlib.gunzipSync(response.rawPayload)
126
+ t.equal(response.headers['content-encoding'], 'gzip')
127
+ t.equal(payload.toString('utf-8'), file)
128
+ })
129
+
130
+ t.test('it should not compress data when `global` is `false` unless `compress` routes settings have been set up', async (t) => {
131
+ t.plan(9)
132
+
133
+ let usedCustom = false
134
+ const customZlib = { createGzip: () => (usedCustom = true) && zlib.createGzip() }
135
+
136
+ const fastify = Fastify()
137
+ await fastify.register(compressPlugin, { global: false })
138
+
139
+ fastify.get('/', (request, reply) => {
140
+ // compress function should still be available
141
+ t.type(reply.compress, 'function')
142
+
143
+ reply.send({ foo: 1 })
144
+ })
145
+
146
+ fastify.get('/custom', {
147
+ compress: { zlib: customZlib }
148
+ }, (request, reply) => {
149
+ reply
150
+ .type('text/plain')
151
+ .compress(createReadStream('./package.json'))
152
+ })
153
+
154
+ fastify.get('/standard', {
155
+ compress: { threshold: 1 }
156
+ }, (request, reply) => {
157
+ reply.send({ foo: 1 })
158
+ })
159
+
160
+ await fastify.inject({
161
+ url: '/',
162
+ method: 'GET',
163
+ headers: {
164
+ 'accept-encoding': 'gzip'
165
+ }
166
+ }).then((response) => {
167
+ t.equal(usedCustom, false)
168
+
169
+ t.equal(response.headers['content-encoding'], undefined)
170
+ t.equal(response.rawPayload.toString('utf-8'), JSON.stringify({ foo: 1 }))
171
+
172
+ usedCustom = false
173
+ })
174
+
175
+ await fastify.inject({
176
+ url: '/custom',
177
+ method: 'GET',
178
+ headers: {
179
+ 'accept-encoding': 'gzip'
180
+ }
181
+ }).then((response) => {
182
+ t.equal(usedCustom, true)
183
+
184
+ const file = readFileSync('./package.json', 'utf8')
185
+ const payload = zlib.gunzipSync(response.rawPayload)
186
+ t.equal(response.headers['content-encoding'], 'gzip')
187
+ t.equal(payload.toString('utf-8'), file)
188
+ })
189
+
190
+ const response = await fastify.inject({
191
+ url: '/standard',
192
+ method: 'GET',
193
+ headers: {
194
+ 'accept-encoding': 'gzip'
195
+ }
196
+ })
197
+ const payload = zlib.gunzipSync(response.rawPayload)
198
+ t.equal(response.headers['content-encoding'], 'gzip')
199
+ t.equal(payload.toString('utf-8'), JSON.stringify({ foo: 1 }))
200
+ })
201
+
202
+ t.test('it should not compress data when route `compress` option is set to `false`', async (t) => {
203
+ t.plan(2)
204
+
205
+ const content = { message: 'Hello World!' }
206
+
207
+ const fastify = Fastify()
208
+ await fastify.register(compressPlugin, { global: false })
209
+
210
+ fastify.get('/', {
211
+ compress: false
212
+ }, (request, reply) => {
213
+ reply.send(content)
214
+ })
215
+
216
+ const response = await fastify.inject({
217
+ url: '/',
218
+ method: 'GET',
219
+ headers: {
220
+ 'accept-encoding': 'gzip'
221
+ }
222
+ })
223
+ t.equal(response.headers['content-encoding'], undefined)
224
+ t.equal(response.rawPayload.toString('utf-8'), JSON.stringify(content))
225
+ })
226
+
227
+ t.test('it should throw an error on invalid route `compress` settings', async (t) => {
228
+ t.plan(2)
229
+
230
+ const fastify = Fastify()
231
+ await fastify.register(compressPlugin, { global: false })
232
+
233
+ fastify.get('/', {
234
+ compress: 'bad config'
235
+ }, (request, reply) => {
236
+ reply.send('')
237
+ })
238
+
239
+ await fastify.inject({
240
+ url: '/',
241
+ method: 'GET',
242
+ headers: {
243
+ 'accept-encoding': 'gzip'
244
+ }
245
+ }).catch((err) => {
246
+ t.type(err, Error)
247
+ t.equal(err.message, 'Unknown value for route compress configuration')
248
+ })
249
+ })
250
+ })
251
+
252
+ test('When `compress.removeContentLengthHeader` is `false`, it should not remove `Content-Length` header :', async (t) => {
253
+ t.test('using `reply.compress()`', async (t) => {
254
+ t.plan(3)
255
+
256
+ const fastify = Fastify()
257
+ await fastify.register(compressPlugin, { global: true })
258
+
259
+ fastify.get('/', {
260
+ compress: { removeContentLengthHeader: false }
261
+ }, (request, reply) => {
262
+ readFile('./package.json', 'utf8', (err, data) => {
263
+ if (err) {
264
+ return reply.send(err)
265
+ }
266
+
267
+ reply
268
+ .type('text/plain')
269
+ .header('content-length', '' + data.length)
270
+ .compress(data)
271
+ })
272
+ })
273
+
274
+ const response = await fastify.inject({
275
+ url: '/',
276
+ method: 'GET',
277
+ headers: {
278
+ 'accept-encoding': 'deflate'
279
+ }
280
+ })
281
+ const file = readFileSync('./package.json', 'utf8')
282
+ const payload = zlib.inflateSync(response.rawPayload)
283
+ t.equal(response.headers['content-encoding'], 'deflate')
284
+ t.equal(response.headers['content-length'], payload.length.toString())
285
+ t.equal(payload.toString('utf-8'), file)
286
+ })
287
+
288
+ t.test('using `onSend` hook', async (t) => {
289
+ t.plan(3)
290
+
291
+ const fastify = Fastify()
292
+ await fastify.register(compressPlugin, { global: true })
293
+
294
+ fastify.get('/', {
295
+ compress: { removeContentLengthHeader: false }
296
+ }, (request, reply) => {
297
+ readFile('./package.json', 'utf8', (err, data) => {
298
+ if (err) {
299
+ return reply.send(err)
300
+ }
301
+
302
+ reply
303
+ .type('text/plain')
304
+ .header('content-length', '' + data.length)
305
+ .send(data)
306
+ })
307
+ })
308
+
309
+ const response = await fastify.inject({
310
+ url: '/',
311
+ method: 'GET',
312
+ headers: {
313
+ 'accept-encoding': 'deflate'
314
+ }
315
+ })
316
+ const file = readFileSync('./package.json', 'utf8')
317
+ const payload = zlib.inflateSync(response.rawPayload)
318
+ t.equal(response.headers['content-encoding'], 'deflate')
319
+ t.equal(response.headers['content-length'], payload.length.toString())
320
+ t.equal(payload.toString('utf-8'), file)
321
+ })
322
+ })
323
+
324
+ test('When using the old routes `{ config: compress }` option :', async (t) => {
325
+ t.test('it should compress data using the route custom provided `createGzip` method', async (t) => {
326
+ t.plan(8)
327
+
328
+ let usedCustomGlobal = false
329
+ let usedCustom = false
330
+ const customZlibGlobal = { createGzip: () => (usedCustomGlobal = true) && zlib.createGzip() }
331
+ const customZlib = { createGzip: () => (usedCustom = true) && zlib.createGzip() }
332
+
333
+ const fastify = Fastify()
334
+ await fastify.register(compressPlugin, { global: false, zlib: customZlibGlobal })
335
+
336
+ fastify.get('/', (request, reply) => {
337
+ reply
338
+ .type('text/plain')
339
+ .compress(createReadStream('./package.json'))
340
+ })
341
+
342
+ fastify.get('/custom', {
343
+ config: {
344
+ compress: { zlib: customZlib }
345
+ }
346
+ }, (request, reply) => {
347
+ reply
348
+ .type('text/plain')
349
+ .compress(createReadStream('./package.json'))
350
+ })
351
+
352
+ await fastify.inject({
353
+ url: '/',
354
+ method: 'GET',
355
+ headers: {
356
+ 'accept-encoding': 'gzip'
357
+ }
358
+ }).then((response) => {
359
+ t.equal(usedCustom, false)
360
+ t.equal(usedCustomGlobal, true)
361
+
362
+ const file = readFileSync('./package.json', 'utf8')
363
+ const payload = zlib.gunzipSync(response.rawPayload)
364
+ t.equal(response.headers['content-encoding'], 'gzip')
365
+ t.equal(payload.toString('utf-8'), file)
366
+
367
+ usedCustom = false
368
+ usedCustomGlobal = false
369
+ })
370
+
371
+ const response = await fastify.inject({
372
+ url: '/custom',
373
+ method: 'GET',
374
+ headers: {
375
+ 'accept-encoding': 'gzip'
376
+ }
377
+ })
378
+ t.equal(usedCustom, true)
379
+ t.equal(usedCustomGlobal, false)
380
+
381
+ const file = readFileSync('./package.json', 'utf8')
382
+ const payload = zlib.gunzipSync(response.rawPayload)
383
+ t.equal(response.headers['content-encoding'], 'gzip')
384
+ t.equal(payload.toString('utf-8'), file)
385
+ })
386
+
387
+ t.test('it should use the old routes `{ config: compress }` options over routes `compress` options', async (t) => {
388
+ t.plan(2)
389
+
390
+ const fastify = Fastify()
391
+ await fastify.register(compressPlugin, { global: false })
392
+
393
+ fastify.get('/', {
394
+ compress: {
395
+ zlib: { createGzip: () => zlib.createGzip() }
396
+ },
397
+ config: {
398
+ compress: 'bad config'
399
+ }
400
+ }, (request, reply) => {
401
+ reply.send('')
402
+ })
403
+
404
+ await fastify.inject({
405
+ url: '/',
406
+ method: 'GET',
407
+ headers: {
408
+ 'accept-encoding': 'gzip'
409
+ }
410
+ }).catch((err) => {
411
+ t.type(err, Error)
412
+ t.equal(err.message, 'Unknown value for route compress configuration')
413
+ })
414
+ })
415
+ })
416
+
417
+ test('It should avoid to trigger `onSend` hook twice', async (t) => {
418
+ t.plan(1)
419
+
420
+ const server = Fastify()
421
+ await server.register(compressPlugin, { threshold: 0 })
422
+
423
+ await server.register(async function (server) {
424
+ server.get('/', async (request, _) => {
425
+ return { hi: true }
426
+ })
427
+ }, { prefix: '/test' })
428
+
429
+ const response = await server.inject({
430
+ url: '/test',
431
+ method: 'GET',
432
+ headers: {
433
+ 'accept-encoding': 'br'
434
+ }
435
+ })
436
+ t.same(JSON.parse(zlib.brotliDecompressSync(response.rawPayload)), { hi: true })
437
+ })