fastify 4.24.0 → 4.24.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.
Files changed (53) hide show
  1. package/fastify.js +1 -1
  2. package/lib/route.js +10 -4
  3. package/package.json +32 -32
  4. package/test/404s.test.js +31 -39
  5. package/test/async-await.test.js +1 -1
  6. package/test/build-certificate.js +90 -1
  7. package/test/close-pipelining.test.js +5 -5
  8. package/test/close.test.js +1 -5
  9. package/test/custom-http-server.test.js +94 -91
  10. package/test/custom-parser.0.test.js +21 -47
  11. package/test/custom-parser.1.test.js +10 -732
  12. package/test/custom-parser.2.test.js +102 -0
  13. package/test/custom-parser.3.test.js +245 -0
  14. package/test/custom-parser.4.test.js +239 -0
  15. package/test/custom-parser.5.test.js +149 -0
  16. package/test/head.test.js +204 -0
  17. package/test/helper.js +30 -8
  18. package/test/hooks-async.test.js +3 -3
  19. package/test/hooks.on-listen.test.js +7 -6
  20. package/test/hooks.test.js +4 -15
  21. package/test/http2/closing.test.js +7 -15
  22. package/test/https/custom-https-server.test.js +43 -40
  23. package/test/listen.1.test.js +101 -0
  24. package/test/listen.2.test.js +103 -0
  25. package/test/listen.3.test.js +87 -0
  26. package/test/listen.4.test.js +164 -0
  27. package/test/listen.deprecated.test.js +3 -9
  28. package/test/logger/instantiation.test.js +25 -16
  29. package/test/logger/logger-test-utils.js +1 -1
  30. package/test/plugin.1.test.js +249 -0
  31. package/test/plugin.2.test.js +328 -0
  32. package/test/plugin.3.test.js +311 -0
  33. package/test/plugin.4.test.js +416 -0
  34. package/test/reply-trailers.test.js +1 -2
  35. package/test/route.1.test.js +309 -0
  36. package/test/route.2.test.js +99 -0
  37. package/test/route.3.test.js +205 -0
  38. package/test/route.4.test.js +131 -0
  39. package/test/route.5.test.js +230 -0
  40. package/test/route.6.test.js +306 -0
  41. package/test/route.7.test.js +370 -0
  42. package/test/route.8.test.js +142 -0
  43. package/test/stream.1.test.js +108 -0
  44. package/test/stream.2.test.js +119 -0
  45. package/test/stream.3.test.js +192 -0
  46. package/test/stream.4.test.js +223 -0
  47. package/test/stream.5.test.js +194 -0
  48. package/test/trust-proxy.test.js +2 -4
  49. package/test/upgrade.test.js +3 -3
  50. package/test/listen.test.js +0 -427
  51. package/test/plugin.test.js +0 -1275
  52. package/test/route.test.js +0 -1762
  53. package/test/stream.test.js +0 -816
@@ -0,0 +1,149 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const test = t.test
5
+ const sget = require('simple-get').concat
6
+ const Fastify = require('../fastify')
7
+ const jsonParser = require('fast-json-body')
8
+ const { getServerUrl, plainTextParser } = require('./helper')
9
+
10
+ process.removeAllListeners('warning')
11
+
12
+ test('cannot remove all content type parsers after binding', t => {
13
+ t.plan(2)
14
+
15
+ const fastify = Fastify()
16
+
17
+ t.teardown(fastify.close.bind(fastify))
18
+
19
+ fastify.listen({ port: 0 }, function (err) {
20
+ t.error(err)
21
+
22
+ t.throws(() => fastify.removeAllContentTypeParsers())
23
+ })
24
+ })
25
+
26
+ test('cannot remove content type parsers after binding', t => {
27
+ t.plan(2)
28
+
29
+ const fastify = Fastify()
30
+
31
+ t.teardown(fastify.close.bind(fastify))
32
+
33
+ fastify.listen({ port: 0 }, function (err) {
34
+ t.error(err)
35
+
36
+ t.throws(() => fastify.removeContentTypeParser('application/json'))
37
+ })
38
+ })
39
+
40
+ test('should be able to override the default json parser after removeAllContentTypeParsers', t => {
41
+ t.plan(5)
42
+
43
+ const fastify = Fastify()
44
+
45
+ fastify.post('/', (req, reply) => {
46
+ reply.send(req.body)
47
+ })
48
+
49
+ fastify.removeAllContentTypeParsers()
50
+
51
+ fastify.addContentTypeParser('application/json', function (req, payload, done) {
52
+ t.ok('called')
53
+ jsonParser(payload, function (err, body) {
54
+ done(err, body)
55
+ })
56
+ })
57
+
58
+ fastify.listen({ port: 0 }, err => {
59
+ t.error(err)
60
+
61
+ sget({
62
+ method: 'POST',
63
+ url: getServerUrl(fastify),
64
+ body: '{"hello":"world"}',
65
+ headers: {
66
+ 'Content-Type': 'application/json'
67
+ }
68
+ }, (err, response, body) => {
69
+ t.error(err)
70
+ t.equal(response.statusCode, 200)
71
+ t.same(body.toString(), JSON.stringify({ hello: 'world' }))
72
+ fastify.close()
73
+ })
74
+ })
75
+ })
76
+
77
+ test('should be able to override the default plain text parser after removeAllContentTypeParsers', t => {
78
+ t.plan(5)
79
+
80
+ const fastify = Fastify()
81
+
82
+ fastify.post('/', (req, reply) => {
83
+ reply.send(req.body)
84
+ })
85
+
86
+ fastify.removeAllContentTypeParsers()
87
+
88
+ fastify.addContentTypeParser('text/plain', function (req, payload, done) {
89
+ t.ok('called')
90
+ plainTextParser(payload, function (err, body) {
91
+ done(err, body)
92
+ })
93
+ })
94
+
95
+ fastify.listen({ port: 0 }, err => {
96
+ t.error(err)
97
+
98
+ sget({
99
+ method: 'POST',
100
+ url: getServerUrl(fastify),
101
+ body: 'hello world',
102
+ headers: {
103
+ 'Content-Type': 'text/plain'
104
+ }
105
+ }, (err, response, body) => {
106
+ t.error(err)
107
+ t.equal(response.statusCode, 200)
108
+ t.equal(body.toString(), 'hello world')
109
+ fastify.close()
110
+ })
111
+ })
112
+ })
113
+
114
+ test('should be able to add a custom content type parser after removeAllContentTypeParsers', t => {
115
+ t.plan(5)
116
+
117
+ const fastify = Fastify()
118
+
119
+ fastify.post('/', (req, reply) => {
120
+ reply.send(req.body)
121
+ })
122
+
123
+ fastify.removeAllContentTypeParsers()
124
+
125
+ fastify.addContentTypeParser('application/jsoff', function (req, payload, done) {
126
+ t.ok('called')
127
+ jsonParser(payload, function (err, body) {
128
+ done(err, body)
129
+ })
130
+ })
131
+
132
+ fastify.listen({ port: 0 }, err => {
133
+ t.error(err)
134
+
135
+ sget({
136
+ method: 'POST',
137
+ url: getServerUrl(fastify),
138
+ body: '{"hello":"world"}',
139
+ headers: {
140
+ 'Content-Type': 'application/jsoff'
141
+ }
142
+ }, (err, response, body) => {
143
+ t.error(err)
144
+ t.equal(response.statusCode, 200)
145
+ t.same(body.toString(), JSON.stringify({ hello: 'world' }))
146
+ fastify.close()
147
+ })
148
+ })
149
+ })
package/test/head.test.js CHANGED
@@ -56,6 +56,134 @@ test('shorthand - head', t => {
56
56
  }
57
57
  })
58
58
 
59
+ test('shorthand - custom head', t => {
60
+ t.plan(1)
61
+ try {
62
+ fastify.get('/proxy/*', function (req, reply) {
63
+ reply.code(200).send(null)
64
+ })
65
+
66
+ fastify.head('/proxy/*', function (req, reply) {
67
+ reply.headers({ 'x-foo': 'bar' })
68
+ reply.code(200).send(null)
69
+ })
70
+
71
+ t.pass()
72
+ } catch (e) {
73
+ t.fail()
74
+ }
75
+ })
76
+
77
+ test('shorthand - custom head with constraints', t => {
78
+ t.plan(1)
79
+ try {
80
+ fastify.get('/proxy/*', { constraints: { version: '1.0.0' } }, function (req, reply) {
81
+ reply.code(200).send(null)
82
+ })
83
+
84
+ fastify.head('/proxy/*', { constraints: { version: '1.0.0' } }, function (req, reply) {
85
+ reply.headers({ 'x-foo': 'bar' })
86
+ reply.code(200).send(null)
87
+ })
88
+
89
+ t.pass()
90
+ } catch (e) {
91
+ t.fail()
92
+ }
93
+ })
94
+
95
+ test('shorthand - should not reset a head route', t => {
96
+ t.plan(1)
97
+ try {
98
+ fastify.get('/query1', function (req, reply) {
99
+ reply.code(200).send(null)
100
+ })
101
+
102
+ fastify.put('/query1', function (req, reply) {
103
+ reply.code(200).send(null)
104
+ })
105
+
106
+ t.pass()
107
+ } catch (e) {
108
+ t.fail()
109
+ }
110
+ })
111
+
112
+ test('shorthand - should override head route when setting multiple routes', t => {
113
+ t.plan(1)
114
+ try {
115
+ fastify.route({
116
+ method: 'GET',
117
+ url: '/query2',
118
+ handler: function (req, reply) {
119
+ reply.headers({ 'x-foo': 'bar' })
120
+ reply.code(200).send(null)
121
+ }
122
+ })
123
+
124
+ fastify.route({
125
+ method: ['POST', 'PUT', 'HEAD'],
126
+ url: '/query2',
127
+ handler: function (req, reply) {
128
+ reply.headers({ 'x-foo': 'bar' })
129
+ reply.code(200).send(null)
130
+ }
131
+ })
132
+
133
+ t.pass()
134
+ } catch (e) {
135
+ console.log(e)
136
+ t.fail()
137
+ }
138
+ })
139
+
140
+ test('shorthand - should override head route when setting multiple routes', t => {
141
+ t.plan(1)
142
+ try {
143
+ fastify.route({
144
+ method: ['GET'],
145
+ url: '/query3',
146
+ handler: function (req, reply) {
147
+ reply.headers({ 'x-foo': 'bar' })
148
+ reply.code(200).send(null)
149
+ }
150
+ })
151
+
152
+ fastify.route({
153
+ method: ['POST', 'PUT', 'HEAD'],
154
+ url: '/query3',
155
+ handler: function (req, reply) {
156
+ reply.headers({ 'x-foo': 'bar' })
157
+ reply.code(200).send(null)
158
+ }
159
+ })
160
+
161
+ t.pass()
162
+ } catch (e) {
163
+ console.log(e)
164
+ t.fail()
165
+ }
166
+ })
167
+
168
+ test('shorthand - should set get and head route in the same api call', t => {
169
+ t.plan(1)
170
+ try {
171
+ fastify.route({
172
+ method: ['HEAD', 'GET'],
173
+ url: '/query4',
174
+ handler: function (req, reply) {
175
+ reply.headers({ 'x-foo': 'bar' })
176
+ reply.code(200).send(null)
177
+ }
178
+ })
179
+
180
+ t.pass()
181
+ } catch (e) {
182
+ console.log(e)
183
+ t.fail()
184
+ }
185
+ })
186
+
59
187
  test('shorthand - head params', t => {
60
188
  t.plan(1)
61
189
  try {
@@ -76,6 +204,7 @@ test('shorthand - head, querystring schema', t => {
76
204
  })
77
205
  t.pass()
78
206
  } catch (e) {
207
+ console.log(e)
79
208
  t.fail()
80
209
  }
81
210
  })
@@ -88,6 +217,7 @@ test('missing schema - head', t => {
88
217
  })
89
218
  t.pass()
90
219
  } catch (e) {
220
+ console.log(e)
91
221
  t.fail()
92
222
  }
93
223
  })
@@ -161,4 +291,78 @@ fastify.listen({ port: 0 }, err => {
161
291
  t.equal(response.statusCode, 200)
162
292
  })
163
293
  })
294
+
295
+ test('shorthand - request head custom head', t => {
296
+ t.plan(3)
297
+ sget({
298
+ method: 'HEAD',
299
+ url: 'http://localhost:' + fastify.server.address().port + '/proxy/test'
300
+ }, (err, response) => {
301
+ t.error(err)
302
+ t.equal(response.headers['x-foo'], 'bar')
303
+ t.equal(response.statusCode, 200)
304
+ })
305
+ })
306
+
307
+ test('shorthand - request head custom head with constraints', t => {
308
+ t.plan(3)
309
+ sget({
310
+ method: 'HEAD',
311
+ url: 'http://localhost:' + fastify.server.address().port + '/proxy/test',
312
+ headers: {
313
+ version: '1.0.0'
314
+ }
315
+ }, (err, response) => {
316
+ t.error(err)
317
+ t.equal(response.headers['x-foo'], 'bar')
318
+ t.equal(response.statusCode, 200)
319
+ })
320
+ })
321
+
322
+ test('shorthand - should not reset a head route', t => {
323
+ t.plan(2)
324
+ sget({
325
+ method: 'HEAD',
326
+ url: 'http://localhost:' + fastify.server.address().port + '/query1'
327
+ }, (err, response) => {
328
+ t.error(err)
329
+ t.equal(response.statusCode, 200)
330
+ })
331
+ })
332
+
333
+ test('shorthand - should override head route when setting multiple routes', t => {
334
+ t.plan(3)
335
+ sget({
336
+ method: 'HEAD',
337
+ url: 'http://localhost:' + fastify.server.address().port + '/query2'
338
+ }, (err, response) => {
339
+ t.error(err)
340
+ t.equal(response.headers['x-foo'], 'bar')
341
+ t.equal(response.statusCode, 200)
342
+ })
343
+ })
344
+
345
+ test('shorthand - should override head route when setting multiple routes', t => {
346
+ t.plan(3)
347
+ sget({
348
+ method: 'HEAD',
349
+ url: 'http://localhost:' + fastify.server.address().port + '/query3'
350
+ }, (err, response) => {
351
+ t.error(err)
352
+ t.equal(response.headers['x-foo'], 'bar')
353
+ t.equal(response.statusCode, 200)
354
+ })
355
+ })
356
+
357
+ test('shorthand - should set get and head route in the same api call', t => {
358
+ t.plan(3)
359
+ sget({
360
+ method: 'HEAD',
361
+ url: 'http://localhost:' + fastify.server.address().port + '/query4'
362
+ }, (err, response) => {
363
+ t.error(err)
364
+ t.equal(response.headers['x-foo'], 'bar')
365
+ t.equal(response.statusCode, 200)
366
+ })
367
+ })
164
368
  })
package/test/helper.js CHANGED
@@ -3,8 +3,11 @@
3
3
  const sget = require('simple-get').concat
4
4
  const dns = require('node:dns').promises
5
5
  const stream = require('node:stream')
6
+ const { promisify } = require('node:util')
6
7
  const symbols = require('../lib/symbols')
7
8
 
9
+ module.exports.sleep = promisify(setTimeout)
10
+
8
11
  /**
9
12
  * @param method HTTP request method
10
13
  * @param t tap instance
@@ -421,16 +424,35 @@ module.exports.payloadMethod = function (method, t, isSetErrorHandler = false) {
421
424
  })
422
425
  }
423
426
 
424
- module.exports.getLoopbackHost = async () => {
425
- let localhostForURL
427
+ function lookupToIp (lookup) {
428
+ return lookup.family === 6 ? `[${lookup.address}]` : lookup.address
429
+ }
426
430
 
431
+ module.exports.getLoopbackHost = async () => {
427
432
  const lookup = await dns.lookup('localhost')
428
- const localhost = lookup.address
429
- if (lookup.family === 6) {
430
- localhostForURL = `[${lookup.address}]`
431
- } else {
432
- localhostForURL = localhost
433
+ return [lookup.address, lookupToIp(lookup)]
434
+ }
435
+
436
+ module.exports.plainTextParser = function (request, callback) {
437
+ let body = ''
438
+ request.setEncoding('utf8')
439
+ request.on('error', onError)
440
+ request.on('data', onData)
441
+ request.on('end', onEnd)
442
+ function onError (err) {
443
+ callback(err, null)
444
+ }
445
+ function onData (chunk) {
446
+ body += chunk
433
447
  }
448
+ function onEnd () {
449
+ callback(null, body)
450
+ }
451
+ }
434
452
 
435
- return [localhost, localhostForURL]
453
+ module.exports.getServerUrl = function (app) {
454
+ const { address, port } = app.server.address()
455
+ return address === '::1'
456
+ ? `http://[${address}]:${port}`
457
+ : `http://${address}:${port}`
436
458
  }
@@ -6,7 +6,7 @@ const test = t.test
6
6
  const sget = require('simple-get').concat
7
7
  const Fastify = require('../fastify')
8
8
  const fs = require('node:fs')
9
- const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
9
+ const { sleep } = require('./helper')
10
10
 
11
11
  process.removeAllListeners('warning')
12
12
 
@@ -653,7 +653,7 @@ test('onRequest respond with a stream', t => {
653
653
 
654
654
  fastify.addHook('onRequest', async (req, reply) => {
655
655
  return new Promise((resolve, reject) => {
656
- const stream = fs.createReadStream(process.cwd() + '/test/stream.test.js', 'utf8')
656
+ const stream = fs.createReadStream(__filename, 'utf8')
657
657
  // stream.pipe(res)
658
658
  // res.once('finish', resolve)
659
659
  reply.send(stream).then(() => {
@@ -704,7 +704,7 @@ test('preHandler respond with a stream', t => {
704
704
  const order = [1, 2]
705
705
 
706
706
  fastify.addHook('preHandler', async (req, reply) => {
707
- const stream = fs.createReadStream(process.cwd() + '/test/stream.test.js', 'utf8')
707
+ const stream = fs.createReadStream(__filename, 'utf8')
708
708
  reply.raw.once('finish', () => {
709
709
  t.equal(order.shift(), 2)
710
710
  })
@@ -3,14 +3,15 @@
3
3
  const { test, before } = require('tap')
4
4
  const Fastify = require('../fastify')
5
5
  const fp = require('fastify-plugin')
6
- const dns = require('node:dns').promises
7
6
  const split = require('split2')
7
+ const helper = require('./helper')
8
8
 
9
- let localhost
9
+ // fix citgm @aix72-ppc64
10
+ const LISTEN_READYNESS = process.env.CITGM ? 250 : 50
10
11
 
12
+ let localhost
11
13
  before(async function () {
12
- const lookup = await dns.lookup('localhost')
13
- localhost = lookup.address
14
+ [localhost] = await helper.getLoopbackHost()
14
15
  })
15
16
 
16
17
  test('onListen should not be processed when .ready() is called', t => {
@@ -1068,7 +1069,7 @@ test('onListen hooks do not block /1', t => {
1068
1069
  port: 0
1069
1070
  }, err => {
1070
1071
  t.error(err)
1071
- t.ok(new Date() - startDate < 50)
1072
+ t.ok(new Date() - startDate < LISTEN_READYNESS)
1072
1073
  })
1073
1074
  })
1074
1075
 
@@ -1086,5 +1087,5 @@ test('onListen hooks do not block /2', async t => {
1086
1087
  host: 'localhost',
1087
1088
  port: 0
1088
1089
  })
1089
- t.ok(new Date() - startDate < 50)
1090
+ t.ok(new Date() - startDate < LISTEN_READYNESS)
1090
1091
  })
@@ -11,22 +11,11 @@ const split = require('split2')
11
11
  const symbols = require('../lib/symbols.js')
12
12
  const payload = { hello: 'world' }
13
13
  const proxyquire = require('proxyquire')
14
- const { promisify } = require('node:util')
15
14
  const { connect } = require('node:net')
16
-
17
- const sleep = promisify(setTimeout)
15
+ const { sleep, getServerUrl } = require('./helper')
18
16
 
19
17
  process.removeAllListeners('warning')
20
18
 
21
- function getUrl (app) {
22
- const { address, port } = app.server.address()
23
- if (address === '::1') {
24
- return `http://[${address}]:${port}`
25
- } else {
26
- return `http://${address}:${port}`
27
- }
28
- }
29
-
30
19
  test('hooks', t => {
31
20
  t.plan(49)
32
21
  const fastify = Fastify({ exposeHeadRoutes: false })
@@ -760,7 +749,7 @@ test('onRoute hook should able to change the route url', t => {
760
749
 
761
750
  sget({
762
751
  method: 'GET',
763
- url: getUrl(fastify) + encodeURI('/foo')
752
+ url: getServerUrl(fastify) + encodeURI('/foo')
764
753
  }, (err, response, body) => {
765
754
  t.error(err)
766
755
  t.equal(response.statusCode, 200)
@@ -1782,7 +1771,7 @@ test('onRequest respond with a stream', t => {
1782
1771
  const fastify = Fastify()
1783
1772
 
1784
1773
  fastify.addHook('onRequest', (req, reply, done) => {
1785
- const stream = fs.createReadStream(process.cwd() + '/test/stream.test.js', 'utf8')
1774
+ const stream = fs.createReadStream(__filename, 'utf8')
1786
1775
  // stream.pipe(res)
1787
1776
  // res.once('finish', done)
1788
1777
  reply.send(stream)
@@ -1833,7 +1822,7 @@ test('preHandler respond with a stream', t => {
1833
1822
  const order = [1, 2]
1834
1823
 
1835
1824
  fastify.addHook('preHandler', (req, reply, done) => {
1836
- const stream = fs.createReadStream(process.cwd() + '/test/stream.test.js', 'utf8')
1825
+ const stream = fs.createReadStream(__filename, 'utf8')
1837
1826
  reply.send(stream)
1838
1827
  reply.raw.once('finish', () => {
1839
1828
  t.equal(order.shift(), 2)
@@ -6,18 +6,10 @@ const http2 = require('node:http2')
6
6
  const { promisify } = require('node:util')
7
7
  const connect = promisify(http2.connect)
8
8
  const { once } = require('node:events')
9
-
10
9
  const { buildCertificate } = require('../build-certificate')
11
- t.before(buildCertificate)
10
+ const { getServerUrl } = require('../helper')
12
11
 
13
- function getUrl (app) {
14
- const { address, port } = app.server.address()
15
- if (address === '::1') {
16
- return `http://[${address}]:${port}`
17
- } else {
18
- return `http://${address}:${port}`
19
- }
20
- }
12
+ t.before(buildCertificate)
21
13
 
22
14
  t.test('http/2 request while fastify closing', t => {
23
15
  let fastify
@@ -37,7 +29,7 @@ t.test('http/2 request while fastify closing', t => {
37
29
  t.teardown(() => { fastify.close() })
38
30
 
39
31
  t.test('return 200', t => {
40
- const url = getUrl(fastify)
32
+ const url = getServerUrl(fastify)
41
33
  const session = http2.connect(url, function () {
42
34
  this.request({
43
35
  ':method': 'GET',
@@ -84,7 +76,7 @@ t.test('http/2 request while fastify closing - return503OnClosing: false', t =>
84
76
  t.teardown(() => { fastify.close() })
85
77
 
86
78
  t.test('return 200', t => {
87
- const url = getUrl(fastify)
79
+ const url = getServerUrl(fastify)
88
80
  const session = http2.connect(url, function () {
89
81
  this.request({
90
82
  ':method': 'GET',
@@ -120,7 +112,7 @@ t.test('http/2 closes successfully with async await', async t => {
120
112
 
121
113
  await fastify.listen({ port: 0 })
122
114
 
123
- const url = getUrl(fastify)
115
+ const url = getServerUrl(fastify)
124
116
  const session = await connect(url)
125
117
  // An error might or might not happen, as it's OS dependent.
126
118
  session.on('error', () => {})
@@ -139,7 +131,7 @@ t.test('https/2 closes successfully with async await', async t => {
139
131
 
140
132
  await fastify.listen({ port: 0 })
141
133
 
142
- const url = getUrl(fastify)
134
+ const url = getServerUrl(fastify)
143
135
  const session = await connect(url)
144
136
  // An error might or might not happen, as it's OS dependent.
145
137
  session.on('error', () => {})
@@ -162,7 +154,7 @@ t.test('http/2 server side session emits a timeout event', async t => {
162
154
 
163
155
  await fastify.listen({ port: 0 })
164
156
 
165
- const url = getUrl(fastify)
157
+ const url = getServerUrl(fastify)
166
158
  const session = await connect(url)
167
159
  const req = session.request({
168
160
  ':method': 'GET',