@fastify/compress 7.0.1 → 7.0.3
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/index.js +19 -20
- package/lib/utils.js +42 -1
- package/package.json +6 -6
- package/test/global-compress.test.js +152 -80
- package/test/regression/issue-288.test.js +62 -0
- package/test/routes-compress.test.js +21 -10
- package/test/utils.test.js +43 -1
- package/types/index.d.ts +14 -7
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('tap')
|
|
4
|
+
const Fastify = require('fastify')
|
|
5
|
+
const fastifyCompress = require('../..')
|
|
6
|
+
const { request } = require('node:http')
|
|
7
|
+
|
|
8
|
+
function fetch (url) {
|
|
9
|
+
return new Promise(function (resolve, reject) {
|
|
10
|
+
request(url, function (response) {
|
|
11
|
+
// we need to use Buffer.concat to prevent wrong utf8 handling
|
|
12
|
+
let body = Buffer.from('')
|
|
13
|
+
response.on('data', function (chunk) {
|
|
14
|
+
body = Buffer.concat([body, Buffer.from(chunk, 'utf-8')])
|
|
15
|
+
})
|
|
16
|
+
response.once('error', reject)
|
|
17
|
+
response.once('end', function () {
|
|
18
|
+
resolve(body.toString())
|
|
19
|
+
})
|
|
20
|
+
})
|
|
21
|
+
.once('error', reject)
|
|
22
|
+
.end()
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
test('should not corrupt the file content', async (t) => {
|
|
27
|
+
t.plan(2)
|
|
28
|
+
|
|
29
|
+
// provide 2 byte unicode content
|
|
30
|
+
const twoByteUnicodeContent = new Array(5_000)
|
|
31
|
+
.fill('0')
|
|
32
|
+
.map(() => {
|
|
33
|
+
const random = new Array(10).fill('A').join('🍃')
|
|
34
|
+
return random + '- FASTIFY COMPRESS,🍃 FASTIFY COMPRESS'
|
|
35
|
+
})
|
|
36
|
+
.join('\n')
|
|
37
|
+
const fastify = new Fastify()
|
|
38
|
+
t.teardown(() => fastify.close())
|
|
39
|
+
|
|
40
|
+
fastify.register(async (instance, opts) => {
|
|
41
|
+
await fastify.register(fastifyCompress)
|
|
42
|
+
// compression
|
|
43
|
+
instance.get('/compress', async (req, reply) => {
|
|
44
|
+
return twoByteUnicodeContent
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
// no compression
|
|
49
|
+
fastify.get('/no-compress', async (req, reply) => {
|
|
50
|
+
return twoByteUnicodeContent
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const address = await fastify.listen({ port: 0, host: '127.0.0.1' })
|
|
54
|
+
|
|
55
|
+
const [body1, body2] = await Promise.all([
|
|
56
|
+
fetch(`${address}/compress`),
|
|
57
|
+
fetch(`${address}/no-compress`)
|
|
58
|
+
])
|
|
59
|
+
|
|
60
|
+
t.equal(body1, body2)
|
|
61
|
+
t.equal(body1, twoByteUnicodeContent)
|
|
62
|
+
})
|
|
@@ -8,7 +8,7 @@ const compressPlugin = require('../index')
|
|
|
8
8
|
|
|
9
9
|
test('When using routes `compress` settings :', async (t) => {
|
|
10
10
|
t.test('it should compress data using the route custom provided `createDeflate` method', async (t) => {
|
|
11
|
-
t.plan(
|
|
11
|
+
t.plan(12)
|
|
12
12
|
|
|
13
13
|
let usedCustomGlobal = false
|
|
14
14
|
let usedCustom = false
|
|
@@ -44,6 +44,7 @@ test('When using routes `compress` settings :', async (t) => {
|
|
|
44
44
|
|
|
45
45
|
const file = readFileSync('./package.json', 'utf8')
|
|
46
46
|
const payload = zlib.inflateSync(response.rawPayload)
|
|
47
|
+
t.equal(response.headers.vary, 'accept-encoding')
|
|
47
48
|
t.equal(response.headers['content-encoding'], 'deflate')
|
|
48
49
|
t.notOk(response.headers['content-length'], 'no content length')
|
|
49
50
|
t.equal(payload.toString('utf-8'), file)
|
|
@@ -64,13 +65,14 @@ test('When using routes `compress` settings :', async (t) => {
|
|
|
64
65
|
|
|
65
66
|
const file = readFileSync('./package.json', 'utf8')
|
|
66
67
|
const payload = zlib.inflateSync(response.rawPayload)
|
|
68
|
+
t.equal(response.headers.vary, 'accept-encoding')
|
|
67
69
|
t.equal(response.headers['content-encoding'], 'deflate')
|
|
68
70
|
t.notOk(response.headers['content-length'], 'no content length')
|
|
69
71
|
t.equal(payload.toString('utf-8'), file)
|
|
70
72
|
})
|
|
71
73
|
|
|
72
74
|
t.test('it should compress data using the route custom provided `createGzip` method', async (t) => {
|
|
73
|
-
t.plan(
|
|
75
|
+
t.plan(10)
|
|
74
76
|
|
|
75
77
|
let usedCustomGlobal = false
|
|
76
78
|
let usedCustom = false
|
|
@@ -104,6 +106,7 @@ test('When using routes `compress` settings :', async (t) => {
|
|
|
104
106
|
|
|
105
107
|
const file = readFileSync('./package.json', 'utf8')
|
|
106
108
|
const payload = zlib.gunzipSync(response.rawPayload)
|
|
109
|
+
t.equal(response.headers.vary, 'accept-encoding')
|
|
107
110
|
t.equal(response.headers['content-encoding'], 'gzip')
|
|
108
111
|
t.equal(payload.toString('utf-8'), file)
|
|
109
112
|
|
|
@@ -123,12 +126,13 @@ test('When using routes `compress` settings :', async (t) => {
|
|
|
123
126
|
|
|
124
127
|
const file = readFileSync('./package.json', 'utf8')
|
|
125
128
|
const payload = zlib.gunzipSync(response.rawPayload)
|
|
129
|
+
t.equal(response.headers.vary, 'accept-encoding')
|
|
126
130
|
t.equal(response.headers['content-encoding'], 'gzip')
|
|
127
131
|
t.equal(payload.toString('utf-8'), file)
|
|
128
132
|
})
|
|
129
133
|
|
|
130
134
|
t.test('it should not compress data when `global` is `false` unless `compress` routes settings have been set up', async (t) => {
|
|
131
|
-
t.plan(
|
|
135
|
+
t.plan(12)
|
|
132
136
|
|
|
133
137
|
let usedCustom = false
|
|
134
138
|
const customZlib = { createGzip: () => (usedCustom = true) && zlib.createGzip() }
|
|
@@ -165,8 +169,8 @@ test('When using routes `compress` settings :', async (t) => {
|
|
|
165
169
|
}
|
|
166
170
|
}).then((response) => {
|
|
167
171
|
t.equal(usedCustom, false)
|
|
168
|
-
|
|
169
|
-
t.
|
|
172
|
+
t.notOk(response.headers.vary)
|
|
173
|
+
t.notOk(response.headers['content-encoding'])
|
|
170
174
|
t.equal(response.rawPayload.toString('utf-8'), JSON.stringify({ foo: 1 }))
|
|
171
175
|
|
|
172
176
|
usedCustom = false
|
|
@@ -183,6 +187,7 @@ test('When using routes `compress` settings :', async (t) => {
|
|
|
183
187
|
|
|
184
188
|
const file = readFileSync('./package.json', 'utf8')
|
|
185
189
|
const payload = zlib.gunzipSync(response.rawPayload)
|
|
190
|
+
t.equal(response.headers.vary, 'accept-encoding')
|
|
186
191
|
t.equal(response.headers['content-encoding'], 'gzip')
|
|
187
192
|
t.equal(payload.toString('utf-8'), file)
|
|
188
193
|
})
|
|
@@ -195,12 +200,13 @@ test('When using routes `compress` settings :', async (t) => {
|
|
|
195
200
|
}
|
|
196
201
|
})
|
|
197
202
|
const payload = zlib.gunzipSync(response.rawPayload)
|
|
203
|
+
t.equal(response.headers.vary, 'accept-encoding')
|
|
198
204
|
t.equal(response.headers['content-encoding'], 'gzip')
|
|
199
205
|
t.equal(payload.toString('utf-8'), JSON.stringify({ foo: 1 }))
|
|
200
206
|
})
|
|
201
207
|
|
|
202
208
|
t.test('it should not compress data when route `compress` option is set to `false`', async (t) => {
|
|
203
|
-
t.plan(
|
|
209
|
+
t.plan(3)
|
|
204
210
|
|
|
205
211
|
const content = { message: 'Hello World!' }
|
|
206
212
|
|
|
@@ -220,7 +226,8 @@ test('When using routes `compress` settings :', async (t) => {
|
|
|
220
226
|
'accept-encoding': 'gzip'
|
|
221
227
|
}
|
|
222
228
|
})
|
|
223
|
-
t.
|
|
229
|
+
t.notOk(response.headers.vary)
|
|
230
|
+
t.notOk(response.headers['content-encoding'])
|
|
224
231
|
t.equal(response.rawPayload.toString('utf-8'), JSON.stringify(content))
|
|
225
232
|
})
|
|
226
233
|
|
|
@@ -244,7 +251,7 @@ test('When using routes `compress` settings :', async (t) => {
|
|
|
244
251
|
|
|
245
252
|
test('When `compress.removeContentLengthHeader` is `false`, it should not remove `Content-Length` header :', async (t) => {
|
|
246
253
|
t.test('using `reply.compress()`', async (t) => {
|
|
247
|
-
t.plan(
|
|
254
|
+
t.plan(4)
|
|
248
255
|
|
|
249
256
|
const fastify = Fastify()
|
|
250
257
|
await fastify.register(compressPlugin, { global: true })
|
|
@@ -273,13 +280,14 @@ test('When `compress.removeContentLengthHeader` is `false`, it should not remove
|
|
|
273
280
|
})
|
|
274
281
|
const file = readFileSync('./package.json', 'utf8')
|
|
275
282
|
const payload = zlib.inflateSync(response.rawPayload)
|
|
283
|
+
t.equal(response.headers.vary, 'accept-encoding')
|
|
276
284
|
t.equal(response.headers['content-encoding'], 'deflate')
|
|
277
285
|
t.equal(response.headers['content-length'], payload.length.toString())
|
|
278
286
|
t.equal(payload.toString('utf-8'), file)
|
|
279
287
|
})
|
|
280
288
|
|
|
281
289
|
t.test('using `onSend` hook', async (t) => {
|
|
282
|
-
t.plan(
|
|
290
|
+
t.plan(4)
|
|
283
291
|
|
|
284
292
|
const fastify = Fastify()
|
|
285
293
|
await fastify.register(compressPlugin, { global: true })
|
|
@@ -308,6 +316,7 @@ test('When `compress.removeContentLengthHeader` is `false`, it should not remove
|
|
|
308
316
|
})
|
|
309
317
|
const file = readFileSync('./package.json', 'utf8')
|
|
310
318
|
const payload = zlib.inflateSync(response.rawPayload)
|
|
319
|
+
t.equal(response.headers.vary, 'accept-encoding')
|
|
311
320
|
t.equal(response.headers['content-encoding'], 'deflate')
|
|
312
321
|
t.equal(response.headers['content-length'], payload.length.toString())
|
|
313
322
|
t.equal(payload.toString('utf-8'), file)
|
|
@@ -316,7 +325,7 @@ test('When `compress.removeContentLengthHeader` is `false`, it should not remove
|
|
|
316
325
|
|
|
317
326
|
test('When using the old routes `{ config: compress }` option :', async (t) => {
|
|
318
327
|
t.test('it should compress data using the route custom provided `createGzip` method', async (t) => {
|
|
319
|
-
t.plan(
|
|
328
|
+
t.plan(10)
|
|
320
329
|
|
|
321
330
|
let usedCustomGlobal = false
|
|
322
331
|
let usedCustom = false
|
|
@@ -354,6 +363,7 @@ test('When using the old routes `{ config: compress }` option :', async (t) => {
|
|
|
354
363
|
|
|
355
364
|
const file = readFileSync('./package.json', 'utf8')
|
|
356
365
|
const payload = zlib.gunzipSync(response.rawPayload)
|
|
366
|
+
t.equal(response.headers.vary, 'accept-encoding')
|
|
357
367
|
t.equal(response.headers['content-encoding'], 'gzip')
|
|
358
368
|
t.equal(payload.toString('utf-8'), file)
|
|
359
369
|
|
|
@@ -373,6 +383,7 @@ test('When using the old routes `{ config: compress }` option :', async (t) => {
|
|
|
373
383
|
|
|
374
384
|
const file = readFileSync('./package.json', 'utf8')
|
|
375
385
|
const payload = zlib.gunzipSync(response.rawPayload)
|
|
386
|
+
t.equal(response.headers.vary, 'accept-encoding')
|
|
376
387
|
t.equal(response.headers['content-encoding'], 'gzip')
|
|
377
388
|
t.equal(payload.toString('utf-8'), file)
|
|
378
389
|
})
|
package/test/utils.test.js
CHANGED
|
@@ -4,7 +4,7 @@ const { createReadStream } = require('node:fs')
|
|
|
4
4
|
const { Socket } = require('node:net')
|
|
5
5
|
const { Duplex, PassThrough, Readable, Stream, Transform, Writable } = require('node:stream')
|
|
6
6
|
const { test } = require('tap')
|
|
7
|
-
const { isStream, isDeflate, isGzip } = require('../lib/utils')
|
|
7
|
+
const { isStream, isDeflate, isGzip, intoAsyncIterator } = require('../lib/utils')
|
|
8
8
|
|
|
9
9
|
test('isStream() utility should be able to detect Streams', async (t) => {
|
|
10
10
|
t.plan(12)
|
|
@@ -61,3 +61,45 @@ test('isGzip() utility should be able to detect gzip compressed Buffer', async (
|
|
|
61
61
|
t.equal(isGzip(undefined), false)
|
|
62
62
|
t.equal(isGzip(''), false)
|
|
63
63
|
})
|
|
64
|
+
|
|
65
|
+
test('intoAsyncIterator() utility should handle different data', async (t) => {
|
|
66
|
+
t.plan(8)
|
|
67
|
+
|
|
68
|
+
const buf = Buffer.from('foo')
|
|
69
|
+
const str = 'foo'
|
|
70
|
+
const arr = [str, str]
|
|
71
|
+
const arrayBuffer = new ArrayBuffer(8)
|
|
72
|
+
const typedArray = new Int32Array(arrayBuffer)
|
|
73
|
+
const asyncIterator = (async function * () {
|
|
74
|
+
yield str
|
|
75
|
+
})()
|
|
76
|
+
const obj = {}
|
|
77
|
+
|
|
78
|
+
for await (const buffer of intoAsyncIterator(buf)) {
|
|
79
|
+
t.equal(buffer, buf)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
for await (const string of intoAsyncIterator(str)) {
|
|
83
|
+
t.equal(string, str)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
for await (const chunk of intoAsyncIterator(arr)) {
|
|
87
|
+
t.equal(chunk, str)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
for await (const chunk of intoAsyncIterator(arrayBuffer)) {
|
|
91
|
+
t.equal(chunk.toString(), Buffer.from(arrayBuffer).toString())
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
for await (const chunk of intoAsyncIterator(typedArray)) {
|
|
95
|
+
t.equal(chunk.toString(), Buffer.from(typedArray).toString())
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
for await (const chunk of intoAsyncIterator(asyncIterator)) {
|
|
99
|
+
t.equal(chunk, str)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
for await (const chunk of intoAsyncIterator(obj)) {
|
|
103
|
+
t.equal(chunk, obj)
|
|
104
|
+
}
|
|
105
|
+
})
|
package/types/index.d.ts
CHANGED
|
@@ -2,13 +2,12 @@ import {
|
|
|
2
2
|
FastifyPluginCallback,
|
|
3
3
|
FastifyReply,
|
|
4
4
|
FastifyRequest,
|
|
5
|
+
RouteOptions as FastifyRouteOptions,
|
|
5
6
|
RawServerBase,
|
|
6
|
-
RawServerDefault
|
|
7
|
-
|
|
8
|
-
} from '
|
|
9
|
-
import {
|
|
10
|
-
import { Stream } from 'stream'
|
|
11
|
-
import { BrotliOptions, ZlibOptions } from 'zlib'
|
|
7
|
+
RawServerDefault
|
|
8
|
+
} from 'fastify';
|
|
9
|
+
import { Stream } from 'stream';
|
|
10
|
+
import { BrotliOptions, ZlibOptions } from 'zlib';
|
|
12
11
|
|
|
13
12
|
declare module 'fastify' {
|
|
14
13
|
export interface FastifyContextConfig {
|
|
@@ -26,7 +25,7 @@ declare module 'fastify' {
|
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
interface FastifyReply {
|
|
29
|
-
compress(input: Stream | Input
|
|
28
|
+
compress(input: Stream | Input): void;
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
export interface RouteOptions {
|
|
@@ -61,6 +60,14 @@ type EncodingToken = 'br' | 'deflate' | 'gzip' | 'identity';
|
|
|
61
60
|
|
|
62
61
|
type CompressibleContentTypeFunction = (contentType: string) => boolean;
|
|
63
62
|
|
|
63
|
+
type Input =
|
|
64
|
+
| Buffer
|
|
65
|
+
| NodeJS.TypedArray
|
|
66
|
+
| ArrayBuffer
|
|
67
|
+
| string
|
|
68
|
+
| Iterable<Buffer | string>
|
|
69
|
+
| AsyncIterable<Buffer | string>;
|
|
70
|
+
|
|
64
71
|
declare namespace fastifyCompress {
|
|
65
72
|
|
|
66
73
|
export interface FastifyCompressOptions {
|