fastify 5.3.3 → 5.5.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 (137) hide show
  1. package/.vscode/settings.json +15 -15
  2. package/LICENSE +1 -1
  3. package/README.md +2 -0
  4. package/SECURITY.md +158 -2
  5. package/build/build-validation.js +20 -1
  6. package/docs/Guides/Delay-Accepting-Requests.md +8 -5
  7. package/docs/Guides/Ecosystem.md +20 -5
  8. package/docs/Guides/Migration-Guide-V5.md +6 -10
  9. package/docs/Guides/Recommendations.md +1 -1
  10. package/docs/Reference/ContentTypeParser.md +1 -1
  11. package/docs/Reference/Errors.md +5 -3
  12. package/docs/Reference/Hooks.md +16 -20
  13. package/docs/Reference/Lifecycle.md +2 -2
  14. package/docs/Reference/Logging.md +3 -3
  15. package/docs/Reference/Middleware.md +1 -1
  16. package/docs/Reference/Reply.md +8 -8
  17. package/docs/Reference/Request.md +2 -2
  18. package/docs/Reference/Routes.md +7 -6
  19. package/docs/Reference/Server.md +341 -200
  20. package/docs/Reference/TypeScript.md +1 -3
  21. package/docs/Reference/Validation-and-Serialization.md +56 -4
  22. package/docs/Reference/Warnings.md +2 -1
  23. package/fastify.d.ts +4 -3
  24. package/fastify.js +47 -34
  25. package/lib/configValidator.js +196 -28
  26. package/lib/contentTypeParser.js +41 -48
  27. package/lib/error-handler.js +3 -3
  28. package/lib/errors.js +11 -0
  29. package/lib/handleRequest.js +13 -17
  30. package/lib/pluginOverride.js +3 -1
  31. package/lib/promise.js +23 -0
  32. package/lib/reply.js +24 -30
  33. package/lib/request.js +3 -10
  34. package/lib/route.js +37 -3
  35. package/lib/server.js +36 -35
  36. package/lib/symbols.js +1 -0
  37. package/lib/warnings.js +19 -1
  38. package/package.json +14 -10
  39. package/test/404s.test.js +226 -325
  40. package/test/allow-unsafe-regex.test.js +19 -48
  41. package/test/als.test.js +28 -40
  42. package/test/async-await.test.js +84 -128
  43. package/test/async_hooks.test.js +18 -37
  44. package/test/body-limit.test.js +90 -63
  45. package/test/buffer.test.js +22 -0
  46. package/test/build-certificate.js +1 -1
  47. package/test/case-insensitive.test.js +44 -65
  48. package/test/check.test.js +17 -21
  49. package/test/close-pipelining.test.js +24 -15
  50. package/test/constrained-routes.test.js +231 -0
  51. package/test/custom-http-server.test.js +7 -15
  52. package/test/custom-parser-async.test.js +17 -22
  53. package/test/custom-parser.0.test.js +267 -348
  54. package/test/custom-parser.1.test.js +141 -191
  55. package/test/custom-parser.2.test.js +34 -44
  56. package/test/custom-parser.3.test.js +56 -104
  57. package/test/custom-parser.4.test.js +106 -144
  58. package/test/custom-parser.5.test.js +56 -75
  59. package/test/custom-querystring-parser.test.js +51 -77
  60. package/test/decorator-namespace.test._js_ +3 -4
  61. package/test/decorator.test.js +76 -259
  62. package/test/delete.test.js +101 -110
  63. package/test/diagnostics-channel/404.test.js +7 -15
  64. package/test/diagnostics-channel/async-delay-request.test.js +7 -16
  65. package/test/diagnostics-channel/async-request.test.js +8 -16
  66. package/test/diagnostics-channel/error-request.test.js +7 -15
  67. package/test/diagnostics-channel/sync-delay-request.test.js +7 -16
  68. package/test/diagnostics-channel/sync-request-reply.test.js +9 -16
  69. package/test/diagnostics-channel/sync-request.test.js +9 -16
  70. package/test/fastify-instance.test.js +1 -1
  71. package/test/header-overflow.test.js +18 -29
  72. package/test/helper.js +139 -135
  73. package/test/hooks-async.test.js +259 -235
  74. package/test/hooks.test.js +951 -996
  75. package/test/http-methods/copy.test.js +14 -19
  76. package/test/http-methods/get.test.js +131 -143
  77. package/test/http-methods/head.test.js +53 -84
  78. package/test/http-methods/lock.test.js +31 -31
  79. package/test/http-methods/mkcalendar.test.js +45 -72
  80. package/test/http-methods/mkcol.test.js +5 -9
  81. package/test/http-methods/move.test.js +6 -10
  82. package/test/http-methods/propfind.test.js +34 -44
  83. package/test/http-methods/proppatch.test.js +23 -29
  84. package/test/http-methods/report.test.js +44 -69
  85. package/test/http-methods/search.test.js +67 -82
  86. package/test/http-methods/unlock.test.js +5 -9
  87. package/test/http2/closing.test.js +38 -20
  88. package/test/http2/secure-with-fallback.test.js +31 -28
  89. package/test/https/custom-https-server.test.js +9 -13
  90. package/test/https/https.test.js +56 -53
  91. package/test/input-validation.js +139 -150
  92. package/test/internals/errors.test.js +50 -1
  93. package/test/internals/handle-request.test.js +72 -65
  94. package/test/internals/promise.test.js +63 -0
  95. package/test/internals/reply.test.js +277 -496
  96. package/test/issue-4959.test.js +12 -3
  97. package/test/listen.4.test.js +31 -43
  98. package/test/nullable-validation.test.js +33 -46
  99. package/test/output-validation.test.js +24 -26
  100. package/test/plugin.1.test.js +40 -68
  101. package/test/plugin.2.test.js +108 -120
  102. package/test/plugin.3.test.js +50 -72
  103. package/test/plugin.4.test.js +124 -119
  104. package/test/promises.test.js +42 -63
  105. package/test/proto-poisoning.test.js +78 -97
  106. package/test/register.test.js +8 -18
  107. package/test/request-error.test.js +57 -146
  108. package/test/request-id.test.js +30 -49
  109. package/test/route-hooks.test.js +117 -101
  110. package/test/route-prefix.test.js +194 -133
  111. package/test/route-shorthand.test.js +9 -27
  112. package/test/route.1.test.js +74 -131
  113. package/test/route.8.test.js +9 -17
  114. package/test/router-options.test.js +450 -0
  115. package/test/schema-serialization.test.js +177 -154
  116. package/test/schema-special-usage.test.js +165 -132
  117. package/test/schema-validation.test.js +254 -218
  118. package/test/server.test.js +143 -5
  119. package/test/set-error-handler.test.js +58 -1
  120. package/test/skip-reply-send.test.js +64 -69
  121. package/test/stream.1.test.js +33 -50
  122. package/test/stream.4.test.js +18 -28
  123. package/test/stream.5.test.js +11 -19
  124. package/test/trust-proxy.test.js +32 -58
  125. package/test/types/errors.test-d.ts +13 -1
  126. package/test/types/fastify.test-d.ts +3 -0
  127. package/test/types/request.test-d.ts +1 -0
  128. package/test/types/type-provider.test-d.ts +55 -0
  129. package/test/url-rewriting.test.js +45 -62
  130. package/test/use-semicolon-delimiter.test.js +117 -59
  131. package/test/versioned-routes.test.js +39 -56
  132. package/types/errors.d.ts +11 -1
  133. package/types/hooks.d.ts +1 -1
  134. package/types/instance.d.ts +1 -1
  135. package/types/reply.d.ts +2 -2
  136. package/types/request.d.ts +1 -0
  137. package/.taprc +0 -7
@@ -1,12 +1,11 @@
1
1
  'use strict'
2
2
 
3
3
  const { test } = require('node:test')
4
- const sget = require('simple-get').concat
5
4
  const fs = require('node:fs')
6
5
  const Fastify = require('../fastify')
7
6
 
8
- test('should respond with a stream', (t, testDone) => {
9
- t.plan(6)
7
+ test('should respond with a stream', async t => {
8
+ t.plan(4)
10
9
  const fastify = Fastify()
11
10
 
12
11
  fastify.get('/', function (req, reply) {
@@ -14,26 +13,21 @@ test('should respond with a stream', (t, testDone) => {
14
13
  reply.code(200).send(stream)
15
14
  })
16
15
 
17
- fastify.listen({ port: 0 }, err => {
18
- t.assert.ifError(err)
19
- t.after(() => { fastify.close() })
20
-
21
- sget(`http://localhost:${fastify.server.address().port}`, function (err, response, data) {
22
- t.assert.ifError(err)
23
- t.assert.strictEqual(response.headers['content-type'], undefined)
24
- t.assert.strictEqual(response.statusCode, 200)
25
-
26
- fs.readFile(__filename, (err, expected) => {
27
- t.assert.ifError(err)
28
- t.assert.strictEqual(expected.toString(), data.toString())
29
- testDone()
30
- })
31
- })
32
- })
16
+ const fastifyServer = await fastify.listen({ port: 0 })
17
+ t.after(() => { fastify.close() })
18
+
19
+ const response = await fetch(fastifyServer)
20
+ t.assert.ok(response.ok)
21
+ t.assert.strictEqual(response.headers.get('content-type'), null)
22
+ t.assert.strictEqual(response.status, 200)
23
+
24
+ const data = await response.text()
25
+ const expected = await fs.promises.readFile(__filename, 'utf8')
26
+ t.assert.strictEqual(expected.toString(), data.toString())
33
27
  })
34
28
 
35
- test('should respond with a stream (error)', (t, testDone) => {
36
- t.plan(3)
29
+ test('should respond with a stream (error)', async t => {
30
+ t.plan(2)
37
31
  const fastify = Fastify()
38
32
 
39
33
  fastify.get('/error', function (req, reply) {
@@ -41,20 +35,16 @@ test('should respond with a stream (error)', (t, testDone) => {
41
35
  reply.code(200).send(stream)
42
36
  })
43
37
 
44
- fastify.listen({ port: 0 }, err => {
45
- t.assert.ifError(err)
46
- t.after(() => { fastify.close() })
38
+ const fastifyServer = await fastify.listen({ port: 0 })
39
+ t.after(() => fastify.close())
47
40
 
48
- sget(`http://localhost:${fastify.server.address().port}/error`, function (err, response) {
49
- t.assert.ifError(err)
50
- t.assert.strictEqual(response.statusCode, 500)
51
- testDone()
52
- })
53
- })
41
+ const response = await fetch(`${fastifyServer}/error`)
42
+ t.assert.ok(!response.ok)
43
+ t.assert.strictEqual(response.status, 500)
54
44
  })
55
45
 
56
- test('should trigger the onSend hook', (t, testDone) => {
57
- t.plan(4)
46
+ test('should trigger the onSend hook', async (t) => {
47
+ t.plan(3)
58
48
  const fastify = Fastify()
59
49
 
60
50
  fastify.get('/', (req, reply) => {
@@ -67,19 +57,16 @@ test('should trigger the onSend hook', (t, testDone) => {
67
57
  done()
68
58
  })
69
59
 
70
- fastify.inject({
60
+ const res = await fastify.inject({
71
61
  url: '/'
72
- }, (err, res) => {
73
- t.assert.ifError(err)
74
- t.assert.strictEqual(res.headers['content-type'], 'application/javascript')
75
- t.assert.strictEqual(res.payload, fs.readFileSync(__filename, 'utf8'))
76
- fastify.close()
77
- testDone()
78
62
  })
63
+ t.assert.strictEqual(res.headers['content-type'], 'application/javascript')
64
+ t.assert.strictEqual(res.payload, fs.readFileSync(__filename, 'utf8'))
65
+ return fastify.close()
79
66
  })
80
67
 
81
- test('should trigger the onSend hook only twice if pumping the stream fails, first with the stream, second with the serialized error', (t, testDone) => {
82
- t.plan(5)
68
+ test('should trigger the onSend hook only twice if pumping the stream fails, first with the stream, second with the serialized error', async t => {
69
+ t.plan(4)
83
70
  const fastify = Fastify()
84
71
 
85
72
  fastify.get('/', (req, reply) => {
@@ -98,14 +85,10 @@ test('should trigger the onSend hook only twice if pumping the stream fails, fir
98
85
  done()
99
86
  })
100
87
 
101
- fastify.listen({ port: 0 }, err => {
102
- t.assert.ifError(err)
103
- t.after(() => { fastify.close() })
88
+ const fastifyServer = await fastify.listen({ port: 0 })
89
+ t.after(() => { fastify.close() })
104
90
 
105
- sget(`http://localhost:${fastify.server.address().port}`, function (err, response) {
106
- t.assert.ifError(err)
107
- t.assert.strictEqual(response.statusCode, 500)
108
- testDone()
109
- })
110
- })
91
+ const response = await fetch(fastifyServer)
92
+ t.assert.ok(!response.ok)
93
+ t.assert.strictEqual(response.status, 500)
111
94
  })
@@ -1,7 +1,6 @@
1
1
  'use strict'
2
2
 
3
3
  const { test } = require('node:test')
4
- const sget = require('simple-get').concat
5
4
  const errors = require('http-errors')
6
5
  const JSONStream = require('JSONStream')
7
6
  const Readable = require('node:stream').Readable
@@ -126,8 +125,8 @@ test('Destroying streams prematurely, log is disabled', (t, testDone) => {
126
125
  })
127
126
  })
128
127
 
129
- test('should respond with a stream1', (t, testDone) => {
130
- t.plan(5)
128
+ test('should respond with a stream1', async (t) => {
129
+ t.plan(4)
131
130
  const fastify = Fastify()
132
131
 
133
132
  fastify.get('/', function (req, reply) {
@@ -137,22 +136,19 @@ test('should respond with a stream1', (t, testDone) => {
137
136
  stream.end({ a: 42 })
138
137
  })
139
138
 
140
- fastify.listen({ port: 0 }, err => {
141
- t.assert.ifError(err)
142
- t.after(() => { fastify.close() })
139
+ const fastifyServer = await fastify.listen({ port: 0 })
140
+ t.after(() => fastify.close())
143
141
 
144
- sget(`http://localhost:${fastify.server.address().port}`, function (err, response, body) {
145
- t.assert.ifError(err)
146
- t.assert.strictEqual(response.headers['content-type'], 'application/json')
147
- t.assert.strictEqual(response.statusCode, 200)
148
- t.assert.deepStrictEqual(JSON.parse(body), [{ hello: 'world' }, { a: 42 }])
149
- testDone()
150
- })
151
- })
142
+ const response = await fetch(fastifyServer)
143
+ t.assert.ok(response.ok)
144
+ t.assert.strictEqual(response.headers.get('content-type'), 'application/json')
145
+ t.assert.strictEqual(response.status, 200)
146
+ const body = await response.text()
147
+ t.assert.deepStrictEqual(JSON.parse(body), [{ hello: 'world' }, { a: 42 }])
152
148
  })
153
149
 
154
- test('return a 404 if the stream emits a 404 error', (t, testDone) => {
155
- t.plan(5)
150
+ test('return a 404 if the stream emits a 404 error', async (t) => {
151
+ t.plan(4)
156
152
 
157
153
  const fastify = Fastify()
158
154
 
@@ -170,17 +166,11 @@ test('return a 404 if the stream emits a 404 error', (t, testDone) => {
170
166
  reply.send(reallyLongStream)
171
167
  })
172
168
 
173
- fastify.listen({ port: 0 }, err => {
174
- t.assert.ifError(err)
175
- t.after(() => { fastify.close() })
176
-
177
- const port = fastify.server.address().port
169
+ const fastifyServer = await fastify.listen({ port: 0 })
170
+ t.after(() => fastify.close())
178
171
 
179
- sget(`http://localhost:${port}`, function (err, response) {
180
- t.assert.ifError(err)
181
- t.assert.strictEqual(response.headers['content-type'], 'application/json; charset=utf-8')
182
- t.assert.strictEqual(response.statusCode, 404)
183
- testDone()
184
- })
185
- })
172
+ const response = await fetch(fastifyServer)
173
+ t.assert.ok(!response.ok)
174
+ t.assert.strictEqual(response.headers.get('content-type'), 'application/json; charset=utf-8')
175
+ t.assert.strictEqual(response.status, 404)
186
176
  })
@@ -4,11 +4,10 @@ const { test } = require('node:test')
4
4
  const proxyquire = require('proxyquire')
5
5
  const fs = require('node:fs')
6
6
  const Readable = require('node:stream').Readable
7
- const sget = require('simple-get').concat
8
7
  const Fastify = require('..')
9
8
 
10
- test('should destroy stream when response is ended', (t, done) => {
11
- t.plan(4)
9
+ test('should destroy stream when response is ended', async (t) => {
10
+ t.plan(3)
12
11
  const stream = require('node:stream')
13
12
  const fastify = Fastify()
14
13
 
@@ -24,20 +23,16 @@ test('should destroy stream when response is ended', (t, done) => {
24
23
  reply.raw.end(Buffer.from('hello\n'))
25
24
  })
26
25
 
27
- fastify.listen({ port: 0 }, err => {
28
- t.assert.ifError(err)
29
- t.after(() => fastify.close())
26
+ const fastifyServer = await fastify.listen({ port: 0 })
27
+ t.after(() => fastify.close())
30
28
 
31
- sget(`http://localhost:${fastify.server.address().port}/error`, function (err, response) {
32
- t.assert.ifError(err)
33
- t.assert.strictEqual(response.statusCode, 200)
34
- done()
35
- })
36
- })
29
+ const response = await fetch(`${fastifyServer}/error`)
30
+ t.assert.ok(response.ok)
31
+ t.assert.strictEqual(response.status, 200)
37
32
  })
38
33
 
39
- test('should mark reply as sent before pumping the payload stream into response for async route handler', (t, done) => {
40
- t.plan(3)
34
+ test('should mark reply as sent before pumping the payload stream into response for async route handler', async (t) => {
35
+ t.plan(2)
41
36
  t.after(() => fastify.close())
42
37
 
43
38
  const handleRequest = proxyquire('../lib/handleRequest', {
@@ -63,14 +58,11 @@ test('should mark reply as sent before pumping the payload stream into response
63
58
  return reply.code(200).send(stream)
64
59
  })
65
60
 
66
- fastify.inject({
61
+ const res = await fastify.inject({
67
62
  url: '/',
68
63
  method: 'GET'
69
- }, (err, res) => {
70
- t.assert.ifError(err)
71
- t.assert.strictEqual(res.payload, fs.readFileSync(__filename, 'utf8'))
72
- done()
73
64
  })
65
+ t.assert.strictEqual(res.payload, fs.readFileSync(__filename, 'utf8'))
74
66
  })
75
67
 
76
68
  test('reply.send handles aborted requests', (t, done) => {
@@ -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
  })
@@ -2,7 +2,6 @@ import { FastifyErrorConstructor } from '@fastify/error'
2
2
  import { expectAssignable } from 'tsd'
3
3
  import { errorCodes } from '../../fastify'
4
4
 
5
- expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_VALIDATION)
6
5
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_NOT_FOUND)
7
6
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_OPTIONS_NOT_OBJ)
8
7
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_QSP_NOT_FN)
@@ -11,6 +10,9 @@ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_SCHEMA_ERROR_FORMAT
11
10
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_OBJ)
12
11
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_ARR)
13
12
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_VALIDATION)
13
+ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_LISTEN_OPTIONS_INVALID)
14
+ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_ERROR_HANDLER_NOT_FN)
15
+ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_ERROR_HANDLER_ALREADY_SET)
14
16
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_CTP_ALREADY_PRESENT)
15
17
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_CTP_INVALID_TYPE)
16
18
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_CTP_EMPTY_TYPE)
@@ -20,11 +22,14 @@ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_CTP_BODY_TOO_LARGE)
20
22
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_CTP_INVALID_MEDIA_TYPE)
21
23
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_CTP_INVALID_CONTENT_LENGTH)
22
24
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_CTP_EMPTY_JSON_BODY)
25
+ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_CTP_INVALID_JSON_BODY)
23
26
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_CTP_INSTANCE_ALREADY_STARTED)
24
27
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_DEC_ALREADY_PRESENT)
25
28
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_DEC_DEPENDENCY_INVALID_TYPE)
26
29
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_DEC_MISSING_DEPENDENCY)
27
30
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_DEC_AFTER_START)
31
+ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_DEC_REFERENCE_TYPE)
32
+ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_DEC_UNDECLARED)
28
33
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_HOOK_INVALID_TYPE)
29
34
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_HOOK_INVALID_HANDLER)
30
35
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_HOOK_INVALID_ASYNC_HANDLER)
@@ -33,7 +38,12 @@ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_MISSING_MIDDLEWARE)
33
38
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_HOOK_TIMEOUT)
34
39
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_LOG_INVALID_DESTINATION)
35
40
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_LOG_INVALID_LOGGER)
41
+ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_LOG_INVALID_LOGGER_INSTANCE)
42
+ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_LOG_INVALID_LOGGER_CONFIG)
43
+ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_LOG_LOGGER_AND_LOGGER_INSTANCE_PROVIDED)
36
44
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_REP_INVALID_PAYLOAD_TYPE)
45
+ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_REP_RESPONSE_BODY_CONSUMED)
46
+ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_REP_READABLE_STREAM_LOCKED)
37
47
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_REP_ALREADY_SENT)
38
48
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_REP_SENT_VALUE)
39
49
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_SEND_INSIDE_ONERR)
@@ -57,6 +67,7 @@ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_FORCE_CLOSE_CONNECT
57
67
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_DUPLICATED_ROUTE)
58
68
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_BAD_URL)
59
69
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_ASYNC_CONSTRAINT)
70
+ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_INVALID_URL)
60
71
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_ROUTE_OPTIONS_NOT_OBJ)
61
72
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_ROUTE_DUPLICATED_HANDLER)
62
73
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_ROUTE_HANDLER_NOT_FN)
@@ -71,6 +82,7 @@ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_REOPENED_SERVER)
71
82
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_INSTANCE_ALREADY_LISTENING)
72
83
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_PLUGIN_VERSION_MISMATCH)
73
84
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE)
85
+ expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_PLUGIN_INVALID_ASYNC_HANDLER)
74
86
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_PLUGIN_CALLBACK_NOT_FN)
75
87
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_PLUGIN_NOT_VALID)
76
88
  expectAssignable<FastifyErrorConstructor>(errorCodes.FST_ERR_ROOT_PLG_BOOTED)
@@ -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 }))
@@ -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 = {}
@@ -1009,6 +1009,37 @@ expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get<{ Reply:
1009
1009
  }
1010
1010
  ))
1011
1011
 
1012
+ // -------------------------------------------------------------------
1013
+ // Reply Status Code (Different Status Codes)
1014
+ // -------------------------------------------------------------------
1015
+
1016
+ expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get(
1017
+ '/',
1018
+ {
1019
+ schema: {
1020
+ response: {
1021
+ 200: {
1022
+ content: {
1023
+ 'text/string': {
1024
+ schema: { type: 'string' }
1025
+ },
1026
+ 'application/json': {
1027
+ schema: { type: 'object', properties: { msg: { type: 'string' } } }
1028
+ }
1029
+ }
1030
+ },
1031
+ 500: { type: 'object', properties: { error: { type: 'string' } } }
1032
+ } as const
1033
+ }
1034
+ },
1035
+ async (_, res) => {
1036
+ res.code(200)
1037
+ res.code(500)
1038
+ expectError(() => res.code(201))
1039
+ expectError(() => res.code(400))
1040
+ }
1041
+ ))
1042
+
1012
1043
  // -------------------------------------------------------------------
1013
1044
  // RouteGeneric Reply Type Return (Different Status Codes)
1014
1045
  // -------------------------------------------------------------------
@@ -1032,6 +1063,30 @@ expectAssignable(server.get<{
1032
1063
  }
1033
1064
  ))
1034
1065
 
1066
+ // -------------------------------------------------------------------
1067
+ // RouteGeneric Status Code (Different Status Codes)
1068
+ // -------------------------------------------------------------------
1069
+
1070
+ expectAssignable(server.get<{
1071
+ Reply: {
1072
+ 200: string | { msg: string }
1073
+ 400: number
1074
+ '5xx': { error: string }
1075
+ }
1076
+ }>(
1077
+ '/',
1078
+ async (_, res) => {
1079
+ res.code(200)
1080
+ res.code(400)
1081
+ res.code(500)
1082
+ res.code(502)
1083
+ expectError(() => res.code(201))
1084
+ expectError(() => res.code(300))
1085
+ expectError(() => res.code(404))
1086
+ return 'hello'
1087
+ }
1088
+ ))
1089
+
1035
1090
  // -------------------------------------------------------------------
1036
1091
  // RouteGeneric Reply Type Return: Non Assignable (Different Status Codes)
1037
1092
  // -------------------------------------------------------------------