fastify 5.3.2 → 5.3.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.
Files changed (48) hide show
  1. package/.vscode/settings.json +22 -0
  2. package/docs/Guides/Ecosystem.md +7 -2
  3. package/docs/Guides/Serverless.md +28 -69
  4. package/docs/Reference/Errors.md +0 -2
  5. package/docs/Reference/Server.md +17 -1
  6. package/eslint.config.js +17 -9
  7. package/fastify.js +6 -2
  8. package/lib/decorate.js +2 -2
  9. package/lib/errors.js +0 -8
  10. package/lib/logger-factory.js +1 -1
  11. package/lib/logger-pino.js +2 -2
  12. package/lib/reply.js +2 -2
  13. package/lib/request.js +1 -1
  14. package/lib/server.js +30 -51
  15. package/package.json +4 -4
  16. package/test/close-pipelining.test.js +5 -4
  17. package/test/decorator.test.js +422 -341
  18. package/test/helper.js +107 -69
  19. package/test/hooks.on-listen.test.js +255 -239
  20. package/test/hooks.on-ready.test.js +110 -92
  21. package/test/inject.test.js +114 -97
  22. package/test/input-validation.js +63 -53
  23. package/test/internals/errors.test.js +1 -11
  24. package/test/internals/hooks.test.js +17 -0
  25. package/test/issue-4959.test.js +2 -2
  26. package/test/logger/response.test.js +19 -20
  27. package/test/options.error-handler.test.js +1 -1
  28. package/test/options.test.js +1 -1
  29. package/test/output-validation.test.js +49 -70
  30. package/test/patch.error-handler.test.js +1 -1
  31. package/test/patch.test.js +1 -1
  32. package/test/plugin.1.test.js +71 -60
  33. package/test/promises.test.js +36 -30
  34. package/test/put.error-handler.test.js +1 -1
  35. package/test/put.test.js +1 -1
  36. package/test/reply-error.test.js +169 -148
  37. package/test/reply-trailers.test.js +119 -108
  38. package/test/schema-feature.test.js +309 -238
  39. package/test/schema-validation.test.js +44 -2
  40. package/test/stream.1.test.js +30 -27
  41. package/test/stream.2.test.js +20 -10
  42. package/test/stream.3.test.js +37 -31
  43. package/test/types/errors.test-d.ts +0 -1
  44. package/test/types/plugin.test-d.ts +1 -1
  45. package/test/types/register.test-d.ts +1 -1
  46. package/test/use-semicolon-delimiter.test.js +1 -1
  47. package/types/errors.d.ts +0 -1
  48. package/test/http2/missing-http2-module.test.js +0 -17
@@ -1,13 +1,12 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
4
- const test = t.test
3
+ const { test, describe } = require('node:test')
5
4
  const Fastify = require('..')
6
5
  const { Readable } = require('node:stream')
7
6
  const { createHash } = require('node:crypto')
8
7
  const { sleep } = require('./helper')
9
8
 
10
- test('send trailers when payload is empty string', t => {
9
+ test('send trailers when payload is empty string', (t, testDone) => {
11
10
  t.plan(5)
12
11
 
13
12
  const fastify = Fastify()
@@ -23,15 +22,16 @@ test('send trailers when payload is empty string', t => {
23
22
  method: 'GET',
24
23
  url: '/'
25
24
  }, (error, res) => {
26
- t.error(error)
27
- t.equal(res.statusCode, 200)
28
- t.equal(res.headers.trailer, 'etag')
29
- t.equal(res.trailers.etag, 'custom-etag')
30
- t.notHas(res.headers, 'content-length')
25
+ t.assert.ifError(error)
26
+ t.assert.strictEqual(res.statusCode, 200)
27
+ t.assert.strictEqual(res.headers.trailer, 'etag')
28
+ t.assert.strictEqual(res.trailers.etag, 'custom-etag')
29
+ t.assert.ok(!res.headers['content-length'])
30
+ testDone()
31
31
  })
32
32
  })
33
33
 
34
- test('send trailers when payload is empty buffer', t => {
34
+ test('send trailers when payload is empty buffer', (t, testDone) => {
35
35
  t.plan(5)
36
36
 
37
37
  const fastify = Fastify()
@@ -47,15 +47,16 @@ test('send trailers when payload is empty buffer', t => {
47
47
  method: 'GET',
48
48
  url: '/'
49
49
  }, (error, res) => {
50
- t.error(error)
51
- t.equal(res.statusCode, 200)
52
- t.equal(res.headers.trailer, 'etag')
53
- t.equal(res.trailers.etag, 'custom-etag')
54
- t.notHas(res.headers, 'content-length')
50
+ t.assert.ifError(error)
51
+ t.assert.strictEqual(res.statusCode, 200)
52
+ t.assert.strictEqual(res.headers.trailer, 'etag')
53
+ t.assert.strictEqual(res.trailers.etag, 'custom-etag')
54
+ t.assert.ok(!res.headers['content-length'])
55
+ testDone()
55
56
  })
56
57
  })
57
58
 
58
- test('send trailers when payload is undefined', t => {
59
+ test('send trailers when payload is undefined', (t, testDone) => {
59
60
  t.plan(5)
60
61
 
61
62
  const fastify = Fastify()
@@ -71,15 +72,16 @@ test('send trailers when payload is undefined', t => {
71
72
  method: 'GET',
72
73
  url: '/'
73
74
  }, (error, res) => {
74
- t.error(error)
75
- t.equal(res.statusCode, 200)
76
- t.equal(res.headers.trailer, 'etag')
77
- t.equal(res.trailers.etag, 'custom-etag')
78
- t.notHas(res.headers, 'content-length')
75
+ t.assert.ifError(error)
76
+ t.assert.strictEqual(res.statusCode, 200)
77
+ t.assert.strictEqual(res.headers.trailer, 'etag')
78
+ t.assert.strictEqual(res.trailers.etag, 'custom-etag')
79
+ t.assert.ok(!res.headers['content-length'])
80
+ testDone()
79
81
  })
80
82
  })
81
83
 
82
- test('send trailers when payload is json', t => {
84
+ test('send trailers when payload is json', (t, testDone) => {
83
85
  t.plan(7)
84
86
 
85
87
  const fastify = Fastify()
@@ -90,7 +92,7 @@ test('send trailers when payload is json', t => {
90
92
 
91
93
  fastify.get('/', function (request, reply) {
92
94
  reply.trailer('Content-MD5', function (reply, payload, done) {
93
- t.equal(data, payload)
95
+ t.assert.strictEqual(data, payload)
94
96
  const hash = createHash('md5')
95
97
  hash.update(payload)
96
98
  done(null, hash.digest('hex'))
@@ -102,23 +104,24 @@ test('send trailers when payload is json', t => {
102
104
  method: 'GET',
103
105
  url: '/'
104
106
  }, (error, res) => {
105
- t.error(error)
106
- t.equal(res.statusCode, 200)
107
- t.equal(res.headers['transfer-encoding'], 'chunked')
108
- t.equal(res.headers.trailer, 'content-md5')
109
- t.equal(res.trailers['content-md5'], md5)
110
- t.notHas(res.headers, 'content-length')
107
+ t.assert.ifError(error)
108
+ t.assert.strictEqual(res.statusCode, 200)
109
+ t.assert.strictEqual(res.headers['transfer-encoding'], 'chunked')
110
+ t.assert.strictEqual(res.headers.trailer, 'content-md5')
111
+ t.assert.strictEqual(res.trailers['content-md5'], md5)
112
+ t.assert.ok(!res.headers['content-length'])
113
+ testDone()
111
114
  })
112
115
  })
113
116
 
114
- test('send trailers when payload is stream', t => {
117
+ test('send trailers when payload is stream', (t, testDone) => {
115
118
  t.plan(7)
116
119
 
117
120
  const fastify = Fastify()
118
121
 
119
122
  fastify.get('/', function (request, reply) {
120
123
  reply.trailer('ETag', function (reply, payload, done) {
121
- t.same(payload, null)
124
+ t.assert.deepStrictEqual(payload, null)
122
125
  done(null, 'custom-etag')
123
126
  })
124
127
  const stream = Readable.from([JSON.stringify({ hello: 'world' })])
@@ -129,16 +132,17 @@ test('send trailers when payload is stream', t => {
129
132
  method: 'GET',
130
133
  url: '/'
131
134
  }, (error, res) => {
132
- t.error(error)
133
- t.equal(res.statusCode, 200)
134
- t.equal(res.headers['transfer-encoding'], 'chunked')
135
- t.equal(res.headers.trailer, 'etag')
136
- t.equal(res.trailers.etag, 'custom-etag')
137
- t.notHas(res.headers, 'content-length')
135
+ t.assert.ifError(error)
136
+ t.assert.strictEqual(res.statusCode, 200)
137
+ t.assert.strictEqual(res.headers['transfer-encoding'], 'chunked')
138
+ t.assert.strictEqual(res.headers.trailer, 'etag')
139
+ t.assert.strictEqual(res.trailers.etag, 'custom-etag')
140
+ t.assert.ok(!res.headers['content-length'])
141
+ testDone()
138
142
  })
139
143
  })
140
144
 
141
- test('send trailers when using async-await', t => {
145
+ test('send trailers when using async-await', (t, testDone) => {
142
146
  t.plan(5)
143
147
 
144
148
  const fastify = Fastify()
@@ -154,15 +158,16 @@ test('send trailers when using async-await', t => {
154
158
  method: 'GET',
155
159
  url: '/'
156
160
  }, (error, res) => {
157
- t.error(error)
158
- t.equal(res.statusCode, 200)
159
- t.equal(res.headers.trailer, 'etag')
160
- t.equal(res.trailers.etag, 'custom-etag')
161
- t.notHas(res.headers, 'content-length')
161
+ t.assert.ifError(error)
162
+ t.assert.strictEqual(res.statusCode, 200)
163
+ t.assert.strictEqual(res.headers.trailer, 'etag')
164
+ t.assert.strictEqual(res.trailers.etag, 'custom-etag')
165
+ t.assert.ok(!res.headers['content-length'])
166
+ testDone()
162
167
  })
163
168
  })
164
169
 
165
- test('error in trailers should be ignored', t => {
170
+ test('error in trailers should be ignored', (t, testDone) => {
166
171
  t.plan(5)
167
172
 
168
173
  const fastify = Fastify()
@@ -178,33 +183,32 @@ test('error in trailers should be ignored', t => {
178
183
  method: 'GET',
179
184
  url: '/'
180
185
  }, (error, res) => {
181
- t.error(error)
182
- t.equal(res.statusCode, 200)
183
- t.equal(res.headers.trailer, 'etag')
184
- t.notHas(res.trailers, 'etag')
185
- t.notHas(res.headers, 'content-length')
186
+ t.assert.ifError(error)
187
+ t.assert.strictEqual(res.statusCode, 200)
188
+ t.assert.strictEqual(res.headers.trailer, 'etag')
189
+ t.assert.ok(!res.trailers['etag'])
190
+ t.assert.ok(!res.headers['content-length'])
191
+ testDone()
186
192
  })
187
193
  })
188
194
 
189
- test('trailer handler counter', t => {
190
- t.plan(2)
191
-
195
+ describe('trailer handler counter', () => {
192
196
  const data = JSON.stringify({ hello: 'world' })
193
197
  const hash = createHash('md5')
194
198
  hash.update(data)
195
199
  const md5 = hash.digest('hex')
196
200
 
197
- t.test('callback with timeout', t => {
201
+ test('callback with timeout', (t, testDone) => {
198
202
  t.plan(9)
199
203
  const fastify = Fastify()
200
204
 
201
205
  fastify.get('/', function (request, reply) {
202
206
  reply.trailer('Return-Early', function (reply, payload, done) {
203
- t.equal(data, payload)
207
+ t.assert.strictEqual(data, payload)
204
208
  done(null, 'return')
205
209
  })
206
210
  reply.trailer('Content-MD5', function (reply, payload, done) {
207
- t.equal(data, payload)
211
+ t.assert.strictEqual(data, payload)
208
212
  const hash = createHash('md5')
209
213
  hash.update(payload)
210
214
  setTimeout(() => {
@@ -218,27 +222,28 @@ test('trailer handler counter', t => {
218
222
  method: 'GET',
219
223
  url: '/'
220
224
  }, (error, res) => {
221
- t.error(error)
222
- t.equal(res.statusCode, 200)
223
- t.equal(res.headers['transfer-encoding'], 'chunked')
224
- t.equal(res.headers.trailer, 'return-early content-md5')
225
- t.equal(res.trailers['return-early'], 'return')
226
- t.equal(res.trailers['content-md5'], md5)
227
- t.notHas(res.headers, 'content-length')
225
+ t.assert.ifError(error)
226
+ t.assert.strictEqual(res.statusCode, 200)
227
+ t.assert.strictEqual(res.headers['transfer-encoding'], 'chunked')
228
+ t.assert.strictEqual(res.headers.trailer, 'return-early content-md5')
229
+ t.assert.strictEqual(res.trailers['return-early'], 'return')
230
+ t.assert.strictEqual(res.trailers['content-md5'], md5)
231
+ t.assert.ok(!res.headers['content-length'])
232
+ testDone()
228
233
  })
229
234
  })
230
235
 
231
- t.test('async-await', t => {
236
+ test('async-await', (t, testDone) => {
232
237
  t.plan(9)
233
238
  const fastify = Fastify()
234
239
 
235
240
  fastify.get('/', function (request, reply) {
236
241
  reply.trailer('Return-Early', async function (reply, payload) {
237
- t.equal(data, payload)
242
+ t.assert.strictEqual(data, payload)
238
243
  return 'return'
239
244
  })
240
245
  reply.trailer('Content-MD5', async function (reply, payload) {
241
- t.equal(data, payload)
246
+ t.assert.strictEqual(data, payload)
242
247
  const hash = createHash('md5')
243
248
  hash.update(payload)
244
249
  await sleep(500)
@@ -251,18 +256,19 @@ test('trailer handler counter', t => {
251
256
  method: 'GET',
252
257
  url: '/'
253
258
  }, (error, res) => {
254
- t.error(error)
255
- t.equal(res.statusCode, 200)
256
- t.equal(res.headers['transfer-encoding'], 'chunked')
257
- t.equal(res.headers.trailer, 'return-early content-md5')
258
- t.equal(res.trailers['return-early'], 'return')
259
- t.equal(res.trailers['content-md5'], md5)
260
- t.notHas(res.headers, 'content-length')
259
+ t.assert.ifError(error)
260
+ t.assert.strictEqual(res.statusCode, 200)
261
+ t.assert.strictEqual(res.headers['transfer-encoding'], 'chunked')
262
+ t.assert.strictEqual(res.headers.trailer, 'return-early content-md5')
263
+ t.assert.strictEqual(res.trailers['return-early'], 'return')
264
+ t.assert.strictEqual(res.trailers['content-md5'], md5)
265
+ t.assert.ok(!res.headers['content-length'])
266
+ testDone()
261
267
  })
262
268
  })
263
269
  })
264
270
 
265
- test('removeTrailer', t => {
271
+ test('removeTrailer', (t, testDone) => {
266
272
  t.plan(6)
267
273
 
268
274
  const fastify = Fastify()
@@ -273,7 +279,7 @@ test('removeTrailer', t => {
273
279
  done(null, 'custom-etag')
274
280
  })
275
281
  reply.trailer('Should-Not-Call', function (reply, payload, done) {
276
- t.fail('it should not called as this trailer is removed')
282
+ t.assert.fail('it should not called as this trailer is removed')
277
283
  done(null, 'should-not-call')
278
284
  })
279
285
  reply.removeTrailer('Should-Not-Call')
@@ -284,28 +290,29 @@ test('removeTrailer', t => {
284
290
  method: 'GET',
285
291
  url: '/'
286
292
  }, (error, res) => {
287
- t.error(error)
288
- t.equal(res.statusCode, 200)
289
- t.equal(res.headers.trailer, 'etag')
290
- t.equal(res.trailers.etag, 'custom-etag')
291
- t.notOk(res.trailers['should-not-call'])
292
- t.notHas(res.headers, 'content-length')
293
+ t.assert.ifError(error)
294
+ t.assert.strictEqual(res.statusCode, 200)
295
+ t.assert.strictEqual(res.headers.trailer, 'etag')
296
+ t.assert.strictEqual(res.trailers.etag, 'custom-etag')
297
+ t.assert.ok(!res.trailers['should-not-call'])
298
+ t.assert.ok(!res.headers['content-length'])
299
+ testDone()
293
300
  })
294
301
  })
295
302
 
296
- test('remove all trailers', t => {
303
+ test('remove all trailers', (t, testDone) => {
297
304
  t.plan(6)
298
305
 
299
306
  const fastify = Fastify()
300
307
 
301
308
  fastify.get('/', function (request, reply) {
302
309
  reply.trailer('ETag', function (reply, payload, done) {
303
- t.fail('it should not called as this trailer is removed')
310
+ t.assert.fail('it should not called as this trailer is removed')
304
311
  done(null, 'custom-etag')
305
312
  })
306
313
  reply.removeTrailer('ETag')
307
314
  reply.trailer('Should-Not-Call', function (reply, payload, done) {
308
- t.fail('it should not called as this trailer is removed')
315
+ t.assert.fail('it should not called as this trailer is removed')
309
316
  done(null, 'should-not-call')
310
317
  })
311
318
  reply.removeTrailer('Should-Not-Call')
@@ -316,33 +323,34 @@ test('remove all trailers', t => {
316
323
  method: 'GET',
317
324
  url: '/'
318
325
  }, (error, res) => {
319
- t.error(error)
320
- t.equal(res.statusCode, 200)
321
- t.notOk(res.headers.trailer)
322
- t.notOk(res.trailers.etag)
323
- t.notOk(res.trailers['should-not-call'])
324
- t.notHas(res.headers, 'content-length')
326
+ t.assert.ifError(error)
327
+ t.assert.strictEqual(res.statusCode, 200)
328
+ t.assert.ok(!res.headers.trailer)
329
+ t.assert.ok(!res.trailers.etag)
330
+ t.assert.ok(!res.trailers['should-not-call'])
331
+ t.assert.ok(!res.headers['content-length'])
332
+ testDone()
325
333
  })
326
334
  })
327
335
 
328
- test('hasTrailer', t => {
336
+ test('hasTrailer', (t, testDone) => {
329
337
  t.plan(10)
330
338
 
331
339
  const fastify = Fastify()
332
340
 
333
341
  fastify.get('/', function (request, reply) {
334
- t.equal(reply.hasTrailer('ETag'), false)
342
+ t.assert.strictEqual(reply.hasTrailer('ETag'), false)
335
343
  reply.trailer('ETag', function (reply, payload, done) {
336
344
  done(null, 'custom-etag')
337
345
  })
338
- t.equal(reply.hasTrailer('ETag'), true)
346
+ t.assert.strictEqual(reply.hasTrailer('ETag'), true)
339
347
  reply.trailer('Should-Not-Call', function (reply, payload, done) {
340
- t.fail('it should not called as this trailer is removed')
348
+ t.assert.fail('it should not called as this trailer is removed')
341
349
  done(null, 'should-not-call')
342
350
  })
343
- t.equal(reply.hasTrailer('Should-Not-Call'), true)
351
+ t.assert.strictEqual(reply.hasTrailer('Should-Not-Call'), true)
344
352
  reply.removeTrailer('Should-Not-Call')
345
- t.equal(reply.hasTrailer('Should-Not-Call'), false)
353
+ t.assert.strictEqual(reply.hasTrailer('Should-Not-Call'), false)
346
354
  reply.send(undefined)
347
355
  })
348
356
 
@@ -350,16 +358,17 @@ test('hasTrailer', t => {
350
358
  method: 'GET',
351
359
  url: '/'
352
360
  }, (error, res) => {
353
- t.error(error)
354
- t.equal(res.statusCode, 200)
355
- t.equal(res.headers.trailer, 'etag')
356
- t.equal(res.trailers.etag, 'custom-etag')
357
- t.notOk(res.trailers['should-not-call'])
358
- t.notHas(res.headers, 'content-length')
361
+ t.assert.ifError(error)
362
+ t.assert.strictEqual(res.statusCode, 200)
363
+ t.assert.strictEqual(res.headers.trailer, 'etag')
364
+ t.assert.strictEqual(res.trailers.etag, 'custom-etag')
365
+ t.assert.ok(!res.trailers['should-not-call'])
366
+ t.assert.ok(!res.headers['content-length'])
367
+ testDone()
359
368
  })
360
369
  })
361
370
 
362
- test('throw error when trailer header name is not allowed', t => {
371
+ test('throw error when trailer header name is not allowed', (t, testDone) => {
363
372
  const INVALID_TRAILERS = [
364
373
  'transfer-encoding',
365
374
  'content-length',
@@ -383,7 +392,7 @@ test('throw error when trailer header name is not allowed', t => {
383
392
  try {
384
393
  reply.trailer(key, () => { })
385
394
  } catch (err) {
386
- t.equal(err.message, `Called reply.trailer with an invalid header name: ${key}`)
395
+ t.assert.strictEqual(err.message, `Called reply.trailer with an invalid header name: ${key}`)
387
396
  }
388
397
  }
389
398
  reply.send('')
@@ -393,12 +402,13 @@ test('throw error when trailer header name is not allowed', t => {
393
402
  method: 'GET',
394
403
  url: '/'
395
404
  }, (error, res) => {
396
- t.error(error)
397
- t.equal(res.statusCode, 200)
405
+ t.assert.ifError(error)
406
+ t.assert.strictEqual(res.statusCode, 200)
407
+ testDone()
398
408
  })
399
409
  })
400
410
 
401
- test('throw error when trailer header value is not function', t => {
411
+ test('throw error when trailer header value is not function', (t, testDone) => {
402
412
  const INVALID_TRAILERS_VALUE = [
403
413
  undefined,
404
414
  null,
@@ -418,7 +428,7 @@ test('throw error when trailer header value is not function', t => {
418
428
  try {
419
429
  reply.trailer('invalid', value)
420
430
  } catch (err) {
421
- t.equal(err.message, `Called reply.trailer('invalid', fn) with an invalid type: ${typeof value}. Expected a function.`)
431
+ t.assert.strictEqual(err.message, `Called reply.trailer('invalid', fn) with an invalid type: ${typeof value}. Expected a function.`)
422
432
  }
423
433
  }
424
434
  reply.send('')
@@ -428,7 +438,8 @@ test('throw error when trailer header value is not function', t => {
428
438
  method: 'GET',
429
439
  url: '/'
430
440
  }, (error, res) => {
431
- t.error(error)
432
- t.equal(res.statusCode, 200)
441
+ t.assert.ifError(error)
442
+ t.assert.strictEqual(res.statusCode, 200)
443
+ testDone()
433
444
  })
434
445
  })