fastify 5.3.2 → 5.4.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.
Files changed (103) hide show
  1. package/README.md +2 -0
  2. package/build/build-validation.js +2 -1
  3. package/docs/Guides/Delay-Accepting-Requests.md +3 -3
  4. package/docs/Guides/Ecosystem.md +16 -7
  5. package/docs/Guides/Serverless.md +28 -69
  6. package/docs/Reference/ContentTypeParser.md +1 -1
  7. package/docs/Reference/Errors.md +2 -4
  8. package/docs/Reference/Hooks.md +14 -14
  9. package/docs/Reference/Logging.md +3 -3
  10. package/docs/Reference/Middleware.md +1 -1
  11. package/docs/Reference/Reply.md +8 -8
  12. package/docs/Reference/Request.md +1 -1
  13. package/docs/Reference/Routes.md +3 -3
  14. package/docs/Reference/Server.md +40 -10
  15. package/docs/Reference/Validation-and-Serialization.md +1 -1
  16. package/eslint.config.js +17 -9
  17. package/fastify.d.ts +2 -1
  18. package/fastify.js +20 -4
  19. package/lib/configValidator.js +1 -1
  20. package/lib/decorate.js +2 -2
  21. package/lib/errors.js +6 -8
  22. package/lib/logger-factory.js +1 -1
  23. package/lib/logger-pino.js +2 -2
  24. package/lib/pluginOverride.js +3 -1
  25. package/lib/reply.js +9 -13
  26. package/lib/request.js +4 -11
  27. package/lib/server.js +30 -51
  28. package/lib/symbols.js +1 -0
  29. package/lib/warnings.js +8 -0
  30. package/package.json +11 -7
  31. package/test/404s.test.js +226 -325
  32. package/test/allow-unsafe-regex.test.js +19 -48
  33. package/test/als.test.js +28 -40
  34. package/test/async-await.test.js +11 -2
  35. package/test/body-limit.test.js +41 -65
  36. package/test/build-certificate.js +1 -1
  37. package/test/close-pipelining.test.js +5 -4
  38. package/test/custom-parser-async.test.js +17 -22
  39. package/test/decorator-namespace.test._js_ +3 -4
  40. package/test/decorator.test.js +422 -341
  41. package/test/diagnostics-channel/async-delay-request.test.js +7 -16
  42. package/test/diagnostics-channel/sync-delay-request.test.js +7 -16
  43. package/test/helper.js +108 -70
  44. package/test/hooks-async.test.js +248 -218
  45. package/test/hooks.on-listen.test.js +255 -239
  46. package/test/hooks.on-ready.test.js +110 -92
  47. package/test/hooks.test.js +910 -769
  48. package/test/http-methods/lock.test.js +31 -31
  49. package/test/http-methods/mkcol.test.js +5 -9
  50. package/test/http-methods/proppatch.test.js +23 -29
  51. package/test/http-methods/report.test.js +44 -69
  52. package/test/http-methods/search.test.js +67 -82
  53. package/test/http2/closing.test.js +38 -20
  54. package/test/http2/secure-with-fallback.test.js +28 -27
  55. package/test/https/https.test.js +56 -53
  56. package/test/inject.test.js +114 -97
  57. package/test/input-validation.js +63 -53
  58. package/test/internals/errors.test.js +0 -10
  59. package/test/internals/handle-request.test.js +49 -66
  60. package/test/internals/hooks.test.js +17 -0
  61. package/test/issue-4959.test.js +14 -5
  62. package/test/listen.4.test.js +31 -43
  63. package/test/logger/response.test.js +19 -20
  64. package/test/nullable-validation.test.js +33 -46
  65. package/test/options.error-handler.test.js +1 -1
  66. package/test/options.test.js +1 -1
  67. package/test/output-validation.test.js +49 -72
  68. package/test/patch.error-handler.test.js +1 -1
  69. package/test/patch.test.js +1 -1
  70. package/test/plugin.1.test.js +71 -60
  71. package/test/plugin.2.test.js +104 -86
  72. package/test/plugin.3.test.js +56 -35
  73. package/test/plugin.4.test.js +124 -119
  74. package/test/promises.test.js +36 -30
  75. package/test/proto-poisoning.test.js +78 -97
  76. package/test/put.error-handler.test.js +1 -1
  77. package/test/put.test.js +1 -1
  78. package/test/reply-error.test.js +169 -148
  79. package/test/reply-trailers.test.js +119 -108
  80. package/test/request-error.test.js +0 -46
  81. package/test/route-hooks.test.js +112 -92
  82. package/test/route-prefix.test.js +194 -133
  83. package/test/schema-feature.test.js +309 -238
  84. package/test/schema-serialization.test.js +177 -154
  85. package/test/schema-special-usage.test.js +165 -132
  86. package/test/schema-validation.test.js +278 -199
  87. package/test/set-error-handler.test.js +58 -1
  88. package/test/skip-reply-send.test.js +64 -69
  89. package/test/stream.1.test.js +30 -27
  90. package/test/stream.2.test.js +20 -10
  91. package/test/stream.3.test.js +37 -31
  92. package/test/trust-proxy.test.js +32 -58
  93. package/test/types/errors.test-d.ts +0 -1
  94. package/test/types/fastify.test-d.ts +3 -0
  95. package/test/types/plugin.test-d.ts +1 -1
  96. package/test/types/register.test-d.ts +1 -1
  97. package/test/types/request.test-d.ts +1 -0
  98. package/test/url-rewriting.test.js +45 -62
  99. package/test/use-semicolon-delimiter.test.js +1 -1
  100. package/types/errors.d.ts +0 -1
  101. package/types/request.d.ts +1 -0
  102. package/.taprc +0 -7
  103. package/test/http2/missing-http2-module.test.js +0 -17
@@ -1,11 +1,10 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
4
- const test = t.test
3
+ const { test } = require('node:test')
5
4
  const split = require('split2')
6
5
  const Fastify = require('..')
7
6
 
8
- test('Destroying streams prematurely', t => {
7
+ test('Destroying streams prematurely', (t, testDone) => {
9
8
  t.plan(6)
10
9
 
11
10
  let fastify = null
@@ -18,7 +17,7 @@ test('Destroying streams prematurely', t => {
18
17
  }
19
18
  })
20
19
  } catch (e) {
21
- t.fail()
20
+ t.assert.fail()
22
21
  }
23
22
  const stream = require('node:stream')
24
23
  const http = require('node:http')
@@ -26,13 +25,14 @@ test('Destroying streams prematurely', t => {
26
25
  // Test that "premature close" errors are logged with level warn
27
26
  logStream.on('data', line => {
28
27
  if (line.res) {
29
- t.equal(line.msg, 'stream closed prematurely')
30
- t.equal(line.level, 30)
28
+ t.assert.strictEqual(line.msg, 'stream closed prematurely')
29
+ t.assert.strictEqual(line.level, 30)
30
+ testDone()
31
31
  }
32
32
  })
33
33
 
34
34
  fastify.get('/', function (request, reply) {
35
- t.pass('Received request')
35
+ t.assert.ok('Received request')
36
36
 
37
37
  let sent = false
38
38
  const reallyLongStream = new stream.Readable({
@@ -48,26 +48,26 @@ test('Destroying streams prematurely', t => {
48
48
  })
49
49
 
50
50
  fastify.listen({ port: 0 }, err => {
51
- t.error(err)
52
- t.teardown(() => { fastify.close() })
51
+ t.assert.ifError(err)
52
+ t.after(() => fastify.close())
53
53
 
54
54
  const port = fastify.server.address().port
55
55
 
56
56
  http.get(`http://localhost:${port}`, function (response) {
57
- t.equal(response.statusCode, 200)
57
+ t.assert.strictEqual(response.statusCode, 200)
58
58
  response.on('readable', function () {
59
59
  response.destroy()
60
60
  })
61
61
 
62
62
  // Node bug? Node never emits 'close' here.
63
63
  response.on('aborted', function () {
64
- t.pass('Response closed')
64
+ t.assert.ok('Response closed')
65
65
  })
66
66
  })
67
67
  })
68
68
  })
69
69
 
70
- test('Destroying streams prematurely should call close method', t => {
70
+ test('Destroying streams prematurely should call close method', (t, testDone) => {
71
71
  t.plan(7)
72
72
 
73
73
  let fastify = null
@@ -80,7 +80,7 @@ test('Destroying streams prematurely should call close method', t => {
80
80
  }
81
81
  })
82
82
  } catch (e) {
83
- t.fail()
83
+ t.assert.fail()
84
84
  }
85
85
  const stream = require('node:stream')
86
86
  const http = require('node:http')
@@ -88,13 +88,13 @@ test('Destroying streams prematurely should call close method', t => {
88
88
  // Test that "premature close" errors are logged with level warn
89
89
  logStream.on('data', line => {
90
90
  if (line.res) {
91
- t.equal(line.msg, 'stream closed prematurely')
92
- t.equal(line.level, 30)
91
+ t.assert.strictEqual(line.msg, 'stream closed prematurely')
92
+ t.assert.strictEqual(line.level, 30)
93
93
  }
94
94
  })
95
95
 
96
96
  fastify.get('/', function (request, reply) {
97
- t.pass('Received request')
97
+ t.assert.ok('Received request')
98
98
 
99
99
  let sent = false
100
100
  const reallyLongStream = new stream.Readable({
@@ -106,30 +106,33 @@ test('Destroying streams prematurely should call close method', t => {
106
106
  }
107
107
  })
108
108
  reallyLongStream.destroy = undefined
109
- reallyLongStream.close = () => t.ok('called')
109
+ reallyLongStream.close = () => {
110
+ t.assert.ok('called')
111
+ testDone()
112
+ }
110
113
  reply.send(reallyLongStream)
111
114
  })
112
115
 
113
116
  fastify.listen({ port: 0 }, err => {
114
- t.error(err)
115
- t.teardown(() => { fastify.close() })
117
+ t.assert.ifError(err)
118
+ t.after(() => { fastify.close() })
116
119
 
117
120
  const port = fastify.server.address().port
118
121
 
119
122
  http.get(`http://localhost:${port}`, function (response) {
120
- t.equal(response.statusCode, 200)
123
+ t.assert.strictEqual(response.statusCode, 200)
121
124
  response.on('readable', function () {
122
125
  response.destroy()
123
126
  })
124
127
  // Node bug? Node never emits 'close' here.
125
128
  response.on('aborted', function () {
126
- t.pass('Response closed')
129
+ t.assert.ok('Response closed')
127
130
  })
128
131
  })
129
132
  })
130
133
  })
131
134
 
132
- test('Destroying streams prematurely should call close method when destroy is not a function', t => {
135
+ test('Destroying streams prematurely should call close method when destroy is not a function', (t, testDone) => {
133
136
  t.plan(7)
134
137
 
135
138
  let fastify = null
@@ -142,7 +145,7 @@ test('Destroying streams prematurely should call close method when destroy is no
142
145
  }
143
146
  })
144
147
  } catch (e) {
145
- t.fail()
148
+ t.assert.fail()
146
149
  }
147
150
  const stream = require('node:stream')
148
151
  const http = require('node:http')
@@ -150,13 +153,13 @@ test('Destroying streams prematurely should call close method when destroy is no
150
153
  // Test that "premature close" errors are logged with level warn
151
154
  logStream.on('data', line => {
152
155
  if (line.res) {
153
- t.equal(line.msg, 'stream closed prematurely')
154
- t.equal(line.level, 30)
156
+ t.assert.strictEqual(line.msg, 'stream closed prematurely')
157
+ t.assert.strictEqual(line.level, 30)
155
158
  }
156
159
  })
157
160
 
158
161
  fastify.get('/', function (request, reply) {
159
- t.pass('Received request')
162
+ t.assert.ok('Received request')
160
163
 
161
164
  let sent = false
162
165
  const reallyLongStream = new stream.Readable({
@@ -168,24 +171,27 @@ test('Destroying streams prematurely should call close method when destroy is no
168
171
  }
169
172
  })
170
173
  reallyLongStream.destroy = true
171
- reallyLongStream.close = () => t.ok('called')
174
+ reallyLongStream.close = () => {
175
+ t.assert.ok('called')
176
+ testDone()
177
+ }
172
178
  reply.send(reallyLongStream)
173
179
  })
174
180
 
175
181
  fastify.listen({ port: 0 }, err => {
176
- t.error(err)
177
- t.teardown(() => { fastify.close() })
182
+ t.assert.ifError(err)
183
+ t.after(() => { fastify.close() })
178
184
 
179
185
  const port = fastify.server.address().port
180
186
 
181
187
  http.get(`http://localhost:${port}`, function (response) {
182
- t.equal(response.statusCode, 200)
188
+ t.assert.strictEqual(response.statusCode, 200)
183
189
  response.on('readable', function () {
184
190
  response.destroy()
185
191
  })
186
192
  // Node bug? Node never emits 'close' here.
187
193
  response.on('aborted', function () {
188
- t.pass('Response closed')
194
+ t.assert.ok('Response closed')
189
195
  })
190
196
  })
191
197
  })
@@ -1,14 +1,10 @@
1
1
  'use strict'
2
2
 
3
3
  const { test, before } = require('node:test')
4
- const sget = require('simple-get').concat
5
4
  const fastify = require('..')
6
5
  const helper = require('./helper')
7
- const { waitForCb } = require('./toolkit')
8
6
 
9
- const noop = () => {}
10
-
11
- const sgetForwardedRequest = (app, forHeader, path, protoHeader, testCaseDone) => {
7
+ const fetchForwardedRequest = async (fastifyServer, forHeader, path, protoHeader) => {
12
8
  const headers = {
13
9
  'X-Forwarded-For': forHeader,
14
10
  'X-Forwarded-Host': 'example.com'
@@ -16,11 +12,10 @@ const sgetForwardedRequest = (app, forHeader, path, protoHeader, testCaseDone) =
16
12
  if (protoHeader) {
17
13
  headers['X-Forwarded-Proto'] = protoHeader
18
14
  }
19
- sget({
20
- method: 'GET',
21
- headers,
22
- url: 'http://localhost:' + app.server.address().port + path
23
- }, testCaseDone || noop)
15
+
16
+ return fetch(fastifyServer + path, {
17
+ headers
18
+ })
24
19
  }
25
20
 
26
21
  const testRequestValues = (t, req, options) => {
@@ -52,8 +47,8 @@ before(async function () {
52
47
  [localhost] = await helper.getLoopbackHost()
53
48
  })
54
49
 
55
- test('trust proxy, not add properties to node req', (t, done) => {
56
- t.plan(14)
50
+ test('trust proxy, not add properties to node req', async t => {
51
+ t.plan(13)
57
52
  const app = fastify({
58
53
  trustProxy: true
59
54
  })
@@ -69,20 +64,14 @@ test('trust proxy, not add properties to node req', (t, done) => {
69
64
  reply.code(200).send({ ip: req.ip, host: req.host })
70
65
  })
71
66
 
72
- app.listen({ port: 0 }, (err) => {
73
- t.assert.ifError(err)
74
-
75
- const completion = waitForCb({ steps: 2 })
76
-
77
- sgetForwardedRequest(app, '1.1.1.1', '/trustproxy', undefined, completion.stepIn)
78
- sgetForwardedRequest(app, '2.2.2.2, 1.1.1.1', '/trustproxychain', undefined, completion.stepIn)
67
+ const fastifyServer = await app.listen({ port: 0 })
79
68
 
80
- completion.patience.then(done)
81
- })
69
+ await fetchForwardedRequest(fastifyServer, '1.1.1.1', '/trustproxy', undefined)
70
+ await fetchForwardedRequest(fastifyServer, '2.2.2.2, 1.1.1.1', '/trustproxychain', undefined)
82
71
  })
83
72
 
84
- test('trust proxy chain', (t, done) => {
85
- t.plan(9)
73
+ test('trust proxy chain', async t => {
74
+ t.plan(8)
86
75
  const app = fastify({
87
76
  trustProxy: [localhost, '192.168.1.1']
88
77
  })
@@ -93,14 +82,12 @@ test('trust proxy chain', (t, done) => {
93
82
  reply.code(200).send({ ip: req.ip, host: req.host })
94
83
  })
95
84
 
96
- app.listen({ port: 0 }, (err) => {
97
- t.assert.ifError(err)
98
- sgetForwardedRequest(app, '192.168.1.1, 1.1.1.1', '/trustproxychain', undefined, done)
99
- })
85
+ const fastifyServer = await app.listen({ port: 0 })
86
+ await fetchForwardedRequest(fastifyServer, '192.168.1.1, 1.1.1.1', '/trustproxychain', undefined)
100
87
  })
101
88
 
102
- test('trust proxy function', (t, done) => {
103
- t.plan(9)
89
+ test('trust proxy function', async t => {
90
+ t.plan(8)
104
91
  const app = fastify({
105
92
  trustProxy: (address) => address === localhost
106
93
  })
@@ -111,14 +98,12 @@ test('trust proxy function', (t, done) => {
111
98
  reply.code(200).send({ ip: req.ip, host: req.host })
112
99
  })
113
100
 
114
- app.listen({ port: 0 }, (err) => {
115
- t.assert.ifError(err)
116
- sgetForwardedRequest(app, '1.1.1.1', '/trustproxyfunc', undefined, done)
117
- })
101
+ const fastifyServer = await app.listen({ port: 0 })
102
+ await fetchForwardedRequest(fastifyServer, '1.1.1.1', '/trustproxyfunc', undefined)
118
103
  })
119
104
 
120
- test('trust proxy number', (t, done) => {
121
- t.plan(10)
105
+ test('trust proxy number', async t => {
106
+ t.plan(9)
122
107
  const app = fastify({
123
108
  trustProxy: 1
124
109
  })
@@ -129,14 +114,12 @@ test('trust proxy number', (t, done) => {
129
114
  reply.code(200).send({ ip: req.ip, host: req.host })
130
115
  })
131
116
 
132
- app.listen({ port: 0 }, (err) => {
133
- t.assert.ifError(err)
134
- sgetForwardedRequest(app, '2.2.2.2, 1.1.1.1', '/trustproxynumber', undefined, done)
135
- })
117
+ const fastifyServer = await app.listen({ port: 0 })
118
+ await fetchForwardedRequest(fastifyServer, '2.2.2.2, 1.1.1.1', '/trustproxynumber', undefined)
136
119
  })
137
120
 
138
- test('trust proxy IP addresses', (t, done) => {
139
- t.plan(10)
121
+ test('trust proxy IP addresses', async t => {
122
+ t.plan(9)
140
123
  const app = fastify({
141
124
  trustProxy: `${localhost}, 2.2.2.2`
142
125
  })
@@ -147,14 +130,12 @@ test('trust proxy IP addresses', (t, done) => {
147
130
  reply.code(200).send({ ip: req.ip, host: req.host })
148
131
  })
149
132
 
150
- app.listen({ port: 0 }, (err) => {
151
- t.assert.ifError(err)
152
- sgetForwardedRequest(app, '3.3.3.3, 2.2.2.2, 1.1.1.1', '/trustproxyipaddrs', undefined, done)
153
- })
133
+ const fastifyServer = await app.listen({ port: 0 })
134
+ await fetchForwardedRequest(fastifyServer, '3.3.3.3, 2.2.2.2, 1.1.1.1', '/trustproxyipaddrs', undefined)
154
135
  })
155
136
 
156
- test('trust proxy protocol', (t, done) => {
157
- t.plan(31)
137
+ test('trust proxy protocol', async t => {
138
+ t.plan(30)
158
139
  const app = fastify({
159
140
  trustProxy: true
160
141
  })
@@ -173,16 +154,9 @@ test('trust proxy protocol', (t, done) => {
173
154
  reply.code(200).send({ ip: req.ip, host: req.host })
174
155
  })
175
156
 
176
- app.listen({ port: 0 }, (err) => {
177
- t.assert.ifError(err)
178
-
179
- const completion = waitForCb({ steps: 3 })
180
- sgetForwardedRequest(app, '1.1.1.1', '/trustproxyprotocol', 'lorem', completion.stepIn)
181
- sgetForwardedRequest(app, '1.1.1.1', '/trustproxynoprotocol', undefined, completion.stepIn)
157
+ const fastifyServer = await app.listen({ port: 0 })
182
158
 
183
- // Allow for sgetForwardedRequest requests above to finish
184
- setTimeout(() => sgetForwardedRequest(app, '1.1.1.1', '/trustproxyprotocols', 'ipsum, dolor', completion.stepIn))
185
-
186
- completion.patience.then(done)
187
- })
159
+ await fetchForwardedRequest(fastifyServer, '1.1.1.1', '/trustproxyprotocol', 'lorem')
160
+ await fetchForwardedRequest(fastifyServer, '1.1.1.1', '/trustproxynoprotocol', undefined)
161
+ await fetchForwardedRequest(fastifyServer, '1.1.1.1', '/trustproxyprotocols', 'ipsum, dolor')
188
162
  })
@@ -52,7 +52,6 @@ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_SCH_DUPLICATE)
52
52
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_SCH_VALIDATION_BUILD)
53
53
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_SCH_SERIALIZATION_BUILD)
54
54
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_SCH_RESPONSE_SCHEMA_NOT_NESTED_2XX)
55
- expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_HTTP2_INVALID_VERSION)
56
55
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_INIT_OPTS_INVALID)
57
56
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_FORCE_CLOSE_CONNECTIONS_IDLE_NOT_AVAILABLE)
58
57
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_DUPLICATED_ROUTE)
@@ -273,3 +273,6 @@ expectType<FastifyErrorCodes>(fastify.errorCodes)
273
273
  fastify({ allowUnsafeRegex: true })
274
274
  fastify({ allowUnsafeRegex: false })
275
275
  expectError(fastify({ allowUnsafeRegex: 'invalid' }))
276
+
277
+ expectAssignable<FastifyInstance>(fastify({ allowErrorHandlerOverride: true }))
278
+ expectAssignable<FastifyInstance>(fastify({ allowErrorHandlerOverride: false }))
@@ -12,7 +12,7 @@ interface TestOptions extends FastifyPluginOptions {
12
12
  }
13
13
  const testOptions: TestOptions = {
14
14
  option1: 'a',
15
- option2: false,
15
+ option2: false
16
16
  }
17
17
  const testPluginOpts: FastifyPluginCallback<TestOptions> = function (instance, opts, done) {
18
18
  expectType<TestOptions>(opts)
@@ -50,7 +50,7 @@ const testPluginWithHttp2WithType = (instance: ServerWithHttp2, opts: FastifyPlu
50
50
  const testPluginWithHttp2WithTypeAsync = async (instance: ServerWithHttp2, opts: FastifyPluginOptions) => { }
51
51
  const testOptions: TestOptions = {
52
52
  option1: 'a',
53
- option2: false,
53
+ option2: false
54
54
  }
55
55
  expectAssignable<ServerWithHttp2>(serverWithHttp2.register(testPluginCallback))
56
56
  expectAssignable<ServerWithHttp2>(serverWithHttp2.register(testPluginAsync))
@@ -78,6 +78,7 @@ const getHandler: RouteHandler = function (request, _reply) {
78
78
  expectType<FastifySchema | undefined>(request.routeOptions.schema)
79
79
  expectType<RouteHandlerMethod>(request.routeOptions.handler)
80
80
  expectType<string | undefined>(request.routeOptions.url)
81
+ expectType<string | undefined>(request.routeOptions.version)
81
82
 
82
83
  expectType<RequestHeadersDefault & RawRequestDefaultExpression['headers']>(request.headers)
83
84
  request.headers = {}
@@ -2,10 +2,9 @@
2
2
 
3
3
  const { test } = require('node:test')
4
4
  const Fastify = require('..')
5
- const sget = require('simple-get').concat
6
5
 
7
- test('Should rewrite url', (t, done) => {
8
- t.plan(5)
6
+ test('Should rewrite url', async t => {
7
+ t.plan(4)
9
8
  const fastify = Fastify({
10
9
  rewriteUrl (req) {
11
10
  t.assert.strictEqual(req.url, '/this-would-404-without-url-rewrite')
@@ -22,24 +21,19 @@ test('Should rewrite url', (t, done) => {
22
21
  }
23
22
  })
24
23
 
25
- fastify.listen({ port: 0 }, function (err) {
26
- t.assert.ifError(err)
27
-
28
- t.after(() => fastify.close())
29
- sget({
30
- method: 'GET',
31
- url: 'http://localhost:' + fastify.server.address().port + '/this-would-404-without-url-rewrite'
32
- }, (err, response, body) => {
33
- t.assert.ifError(err)
34
- t.assert.deepStrictEqual(JSON.parse(body), { hello: 'world' })
35
- t.assert.strictEqual(response.statusCode, 200)
36
- done()
37
- })
38
- })
24
+ const fastifyServer = await fastify.listen({ port: 0 })
25
+
26
+ t.after(() => fastify.close())
27
+
28
+ const result = await fetch(`${fastifyServer}/this-would-404-without-url-rewrite`)
29
+
30
+ t.assert.ok(result.ok)
31
+ t.assert.strictEqual(result.status, 200)
32
+ t.assert.deepStrictEqual(await result.json(), { hello: 'world' })
39
33
  })
40
34
 
41
- test('Should not rewrite if the url is the same', (t, done) => {
42
- t.plan(4)
35
+ test('Should not rewrite if the url is the same', async t => {
36
+ t.plan(3)
43
37
  const fastify = Fastify({
44
38
  rewriteUrl (req) {
45
39
  t.assert.strictEqual(req.url, '/this-would-404-without-url-rewrite')
@@ -56,22 +50,18 @@ test('Should not rewrite if the url is the same', (t, done) => {
56
50
  }
57
51
  })
58
52
 
59
- fastify.listen({ port: 0 }, function (err) {
60
- t.assert.ifError(err)
61
- t.after(() => fastify.close())
62
- sget({
63
- method: 'GET',
64
- url: 'http://localhost:' + fastify.server.address().port + '/this-would-404-without-url-rewrite'
65
- }, (err, response, body) => {
66
- t.assert.ifError(err)
67
- t.assert.strictEqual(response.statusCode, 404)
68
- done()
69
- })
70
- })
53
+ const fastifyServer = await fastify.listen({ port: 0 })
54
+
55
+ t.after(() => fastify.close())
56
+
57
+ const result = await fetch(`${fastifyServer}/this-would-404-without-url-rewrite`)
58
+
59
+ t.assert.ok(!result.ok)
60
+ t.assert.strictEqual(result.status, 404)
71
61
  })
72
62
 
73
- test('Should throw an error', (t, done) => {
74
- t.plan(5)
63
+ test('Should throw an error', async t => {
64
+ t.plan(2)
75
65
  const fastify = Fastify({
76
66
  rewriteUrl (req) {
77
67
  t.assert.strictEqual(req.url, '/this-would-404-without-url-rewrite')
@@ -88,23 +78,20 @@ test('Should throw an error', (t, done) => {
88
78
  }
89
79
  })
90
80
 
91
- fastify.listen({ port: 0 }, function (err) {
92
- t.assert.ifError(err)
93
- t.after(() => fastify.close())
94
- sget({
95
- method: 'GET',
96
- url: 'http://localhost:' + fastify.server.address().port + '/this-would-404-without-url-rewrite'
97
- }, (err, response, body) => {
98
- t.assert.strictEqual(err.code, 'ECONNRESET')
99
- t.assert.strictEqual(response, undefined)
100
- t.assert.strictEqual(body, undefined)
101
- done()
102
- })
103
- })
81
+ const fastifyServer = await fastify.listen({ port: 0 })
82
+
83
+ t.after(() => fastify.close())
84
+
85
+ try {
86
+ await fetch(`${fastifyServer}/this-would-404-without-url-rewrite`)
87
+ t.assert.fail('Expected fetch to throw an error')
88
+ } catch (err) {
89
+ t.assert.ok(err instanceof Error)
90
+ }
104
91
  })
105
92
 
106
- test('Should rewrite url but keep originalUrl unchanged', (t, done) => {
107
- t.plan(7)
93
+ test('Should rewrite url but keep originalUrl unchanged', async t => {
94
+ t.plan(6)
108
95
  const fastify = Fastify({
109
96
  rewriteUrl (req) {
110
97
  t.assert.strictEqual(req.url, '/this-would-404-without-url-rewrite')
@@ -122,18 +109,14 @@ test('Should rewrite url but keep originalUrl unchanged', (t, done) => {
122
109
  }
123
110
  })
124
111
 
125
- fastify.listen({ port: 0 }, function (err) {
126
- t.assert.ifError(err)
127
- t.after(() => fastify.close())
128
- sget({
129
- method: 'GET',
130
- url: 'http://localhost:' + fastify.server.address().port + '/this-would-404-without-url-rewrite'
131
- }, (err, response, body) => {
132
- t.assert.ifError(err)
133
- const parsedBody = JSON.parse(body)
134
- t.assert.deepStrictEqual(parsedBody, { hello: 'world', hostname: 'localhost', port: fastify.server.address().port })
135
- t.assert.strictEqual(response.statusCode, 200)
136
- done()
137
- })
138
- })
112
+ await fastify.listen({ port: 0 })
113
+ const port = fastify.server.address().port
114
+
115
+ t.after(() => fastify.close())
116
+
117
+ const result = await fetch(`http://localhost:${port}/this-would-404-without-url-rewrite`)
118
+
119
+ t.assert.ok(result.ok)
120
+ t.assert.strictEqual(result.status, 200)
121
+ t.assert.deepStrictEqual(await result.json(), { hello: 'world', hostname: 'localhost', port })
139
122
  })
@@ -13,7 +13,7 @@ test('use semicolon delimiter default false', (t, done) => {
13
13
  reply.send(req.query)
14
14
  })
15
15
 
16
- fastify.listen({ port: 0, }, err => {
16
+ fastify.listen({ port: 0 }, err => {
17
17
  t.assert.ifError(err)
18
18
  sget({
19
19
  method: 'GET',
package/types/errors.d.ts CHANGED
@@ -51,7 +51,6 @@ export type FastifyErrorCodes = Record<
51
51
  'FST_ERR_SCH_VALIDATION_BUILD' |
52
52
  'FST_ERR_SCH_SERIALIZATION_BUILD' |
53
53
  'FST_ERR_SCH_RESPONSE_SCHEMA_NOT_NESTED_2XX' |
54
- 'FST_ERR_HTTP2_INVALID_VERSION' |
55
54
  'FST_ERR_INIT_OPTS_INVALID' |
56
55
  'FST_ERR_FORCE_CLOSE_CONNECTIONS_IDLE_NOT_AVAILABLE' |
57
56
  'FST_ERR_DUPLICATED_ROUTE' |
@@ -32,6 +32,7 @@ export interface RequestRouteOptions<ContextConfig = ContextConfigDefault, Schem
32
32
  config: FastifyContextConfig & FastifyRouteConfig & ContextConfig;
33
33
  schema?: SchemaCompiler; // it is empty for 404 requests
34
34
  handler: RouteHandlerMethod;
35
+ version?: string;
35
36
  }
36
37
 
37
38
  /**
package/.taprc DELETED
@@ -1,7 +0,0 @@
1
- # vim: set filetype=yaml :
2
- node-arg:
3
- - '--allow-natives-syntax'
4
-
5
- include:
6
- - 'test/**/*.test.js'
7
- - 'test/**/*.test.mjs'
@@ -1,17 +0,0 @@
1
- 'use strict'
2
-
3
- const { test } = require('node:test')
4
- const proxyquire = require('proxyquire')
5
- const server = proxyquire('../../lib/server', { 'node:http2': null })
6
- const Fastify = proxyquire('../..', { './lib/server.js': server })
7
-
8
- test('should throw when http2 module cannot be found', t => {
9
- t.plan(2)
10
- try {
11
- Fastify({ http2: true })
12
- t.assert.fail('fastify did not throw expected error')
13
- } catch (err) {
14
- t.assert.strictEqual(err.code, 'FST_ERR_HTTP2_INVALID_VERSION')
15
- t.assert.strictEqual(err.message, 'HTTP2 is available only from node >= 8.8.1')
16
- }
17
- })