fastify 4.24.3 → 4.25.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.
- package/README.md +10 -5
- package/SECURITY.md +27 -0
- package/docs/Guides/Ecosystem.md +18 -6
- package/docs/Guides/Getting-Started.md +3 -3
- package/docs/Guides/Plugins-Guide.md +2 -2
- package/docs/Guides/Style-Guide.md +7 -7
- package/docs/Reference/ContentTypeParser.md +2 -0
- package/docs/Reference/Errors.md +171 -397
- package/docs/Reference/Hooks.md +8 -2
- package/docs/Reference/Index.md +2 -0
- package/docs/Reference/Reply.md +16 -5
- package/docs/Reference/Request.md +1 -1
- package/docs/Reference/Routes.md +5 -5
- package/docs/Reference/TypeScript.md +1 -1
- package/docs/Reference/Warnings.md +77 -0
- package/fastify.js +37 -20
- package/lib/decorate.js +2 -2
- package/lib/errors.js +1 -1
- package/lib/hooks.js +1 -1
- package/lib/pluginUtils.js +10 -1
- package/lib/reply.js +5 -5
- package/lib/request.js +14 -7
- package/lib/route.js +9 -5
- package/lib/server.js +20 -27
- package/lib/validation.js +5 -5
- package/lib/warnings.js +110 -40
- package/package.json +3 -3
- package/test/close-pipelining.test.js +4 -4
- package/test/close.test.js +3 -3
- package/test/constrained-routes.test.js +24 -24
- package/test/decorator.test.js +27 -22
- package/test/default-route.test.js +7 -7
- package/test/fastify-instance.test.js +120 -0
- package/test/hooks.on-ready.test.js +16 -0
- package/test/hooks.test.js +1 -3
- package/test/http2/constraint.test.js +1 -1
- package/test/internals/errors.test.js +28 -3
- package/test/internals/reply.test.js +33 -9
- package/test/logger/instantiation.test.js +2 -1
- package/test/plugin.4.test.js +47 -0
- package/test/register.test.js +5 -5
- package/test/reply-trailers.test.js +1 -1
- package/test/route.7.test.js +7 -6
- package/test/schema-examples.test.js +2 -2
- package/test/schema-feature.test.js +11 -11
- package/test/server.test.js +51 -0
- package/test/types/hooks.test-d.ts +124 -1
- package/test/types/instance.test-d.ts +12 -0
- package/test/types/logger.test-d.ts +14 -0
- package/test/types/reply.test-d.ts +25 -6
- package/test/types/request.test-d.ts +3 -2
- package/test/types/route.test-d.ts +31 -0
- package/test/versioned-routes.test.js +7 -6
- package/types/hooks.d.ts +183 -0
- package/types/instance.d.ts +12 -12
- package/types/reply.d.ts +7 -10
- package/types/request.d.ts +2 -1
- package/types/route.d.ts +37 -26
- package/types/utils.d.ts +10 -0
|
@@ -35,6 +35,22 @@ t.test('onReady should be called in order', t => {
|
|
|
35
35
|
fastify.ready(err => t.error(err))
|
|
36
36
|
})
|
|
37
37
|
|
|
38
|
+
t.test('onReady should be called once', async (t) => {
|
|
39
|
+
const app = Fastify()
|
|
40
|
+
let counter = 0
|
|
41
|
+
|
|
42
|
+
app.addHook('onReady', async function () {
|
|
43
|
+
counter++
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const promises = [1, 2, 3, 4, 5].map((id) => app.ready().then(() => id))
|
|
47
|
+
|
|
48
|
+
const result = await Promise.race(promises)
|
|
49
|
+
|
|
50
|
+
t.strictSame(result, 1, 'Should resolve in order')
|
|
51
|
+
t.equal(counter, 1, 'Should call onReady only once')
|
|
52
|
+
})
|
|
53
|
+
|
|
38
54
|
t.test('async onReady should be called in order', async t => {
|
|
39
55
|
t.plan(7)
|
|
40
56
|
const fastify = Fastify()
|
package/test/hooks.test.js
CHANGED
|
@@ -3469,7 +3469,7 @@ test('onRequestAbort should support encapsulation', t => {
|
|
|
3469
3469
|
done()
|
|
3470
3470
|
})
|
|
3471
3471
|
|
|
3472
|
-
fastify.register(async function (_child, _
|
|
3472
|
+
fastify.register(async function (_child, _) {
|
|
3473
3473
|
child = _child
|
|
3474
3474
|
|
|
3475
3475
|
fastify.addHook('onRequestAbort', async function (req) {
|
|
@@ -3488,8 +3488,6 @@ test('onRequestAbort should support encapsulation', t => {
|
|
|
3488
3488
|
t.equal(++order, 3, 'called in route')
|
|
3489
3489
|
}
|
|
3490
3490
|
})
|
|
3491
|
-
|
|
3492
|
-
done()
|
|
3493
3491
|
})
|
|
3494
3492
|
|
|
3495
3493
|
fastify.listen({ port: 0 }, err => {
|
|
@@ -292,7 +292,7 @@ test('FST_ERR_MISSING_MIDDLEWARE', t => {
|
|
|
292
292
|
const error = new errors.FST_ERR_MISSING_MIDDLEWARE()
|
|
293
293
|
t.equal(error.name, 'FastifyError')
|
|
294
294
|
t.equal(error.code, 'FST_ERR_MISSING_MIDDLEWARE')
|
|
295
|
-
t.equal(error.message, 'You must register a plugin for handling middlewares, visit fastify.
|
|
295
|
+
t.equal(error.message, 'You must register a plugin for handling middlewares, visit fastify.dev/docs/latest/Reference/Middleware/ for more info.')
|
|
296
296
|
t.equal(error.statusCode, 500)
|
|
297
297
|
t.ok(error instanceof Error)
|
|
298
298
|
})
|
|
@@ -817,6 +817,31 @@ test('FST_ERR_LISTEN_OPTIONS_INVALID', t => {
|
|
|
817
817
|
t.ok(error instanceof TypeError)
|
|
818
818
|
})
|
|
819
819
|
|
|
820
|
+
test('Ensure that all errors are in Errors.md TOC', t => {
|
|
821
|
+
t.plan(78)
|
|
822
|
+
const errorsMd = readFileSync(resolve(__dirname, '../../docs/Reference/Errors.md'), 'utf8')
|
|
823
|
+
|
|
824
|
+
const exportedKeys = Object.keys(errors)
|
|
825
|
+
for (const key of exportedKeys) {
|
|
826
|
+
if (errors[key].name === 'FastifyError') {
|
|
827
|
+
t.ok(errorsMd.includes(` - [${key.toUpperCase()}](#${key.toLowerCase()})`), key)
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
})
|
|
831
|
+
|
|
832
|
+
test('Ensure that non-existing errors are not in Errors.md TOC', t => {
|
|
833
|
+
t.plan(78)
|
|
834
|
+
const errorsMd = readFileSync(resolve(__dirname, '../../docs/Reference/Errors.md'), 'utf8')
|
|
835
|
+
|
|
836
|
+
const matchRE = / {4}- \[([A-Z0-9_]+)\]\(#[a-z0-9_]+\)/g
|
|
837
|
+
const matches = errorsMd.matchAll(matchRE)
|
|
838
|
+
const exportedKeys = Object.keys(errors)
|
|
839
|
+
|
|
840
|
+
for (const match of matches) {
|
|
841
|
+
t.ok(exportedKeys.indexOf(match[1]) !== -1, match[1])
|
|
842
|
+
}
|
|
843
|
+
})
|
|
844
|
+
|
|
820
845
|
test('Ensure that all errors are in Errors.md documented', t => {
|
|
821
846
|
t.plan(78)
|
|
822
847
|
const errorsMd = readFileSync(resolve(__dirname, '../../docs/Reference/Errors.md'), 'utf8')
|
|
@@ -824,7 +849,7 @@ test('Ensure that all errors are in Errors.md documented', t => {
|
|
|
824
849
|
const exportedKeys = Object.keys(errors)
|
|
825
850
|
for (const key of exportedKeys) {
|
|
826
851
|
if (errors[key].name === 'FastifyError') {
|
|
827
|
-
t.ok(errorsMd.includes(
|
|
852
|
+
t.ok(errorsMd.includes(`<a id="${key.toLowerCase()}">${key.toUpperCase()}</a>`), key)
|
|
828
853
|
}
|
|
829
854
|
}
|
|
830
855
|
})
|
|
@@ -833,7 +858,7 @@ test('Ensure that non-existing errors are not in Errors.md documented', t => {
|
|
|
833
858
|
t.plan(78)
|
|
834
859
|
const errorsMd = readFileSync(resolve(__dirname, '../../docs/Reference/Errors.md'), 'utf8')
|
|
835
860
|
|
|
836
|
-
const matchRE =
|
|
861
|
+
const matchRE = /<a id="[0-9a-zA-Z_]+">([0-9a-zA-Z_]+)<\/a>/g
|
|
837
862
|
const matches = errorsMd.matchAll(matchRE)
|
|
838
863
|
const exportedKeys = Object.keys(errors)
|
|
839
864
|
|
|
@@ -19,7 +19,7 @@ const {
|
|
|
19
19
|
} = require('../../lib/symbols')
|
|
20
20
|
const fs = require('node:fs')
|
|
21
21
|
const path = require('node:path')
|
|
22
|
-
const
|
|
22
|
+
const { FSTDEP019, FSTDEP010 } = require('../../lib/warnings')
|
|
23
23
|
|
|
24
24
|
const agent = new http.Agent({ keepAlive: false })
|
|
25
25
|
|
|
@@ -1466,14 +1466,13 @@ test('should emit deprecation warning when trying to modify the reply.sent prope
|
|
|
1466
1466
|
t.plan(4)
|
|
1467
1467
|
const fastify = Fastify()
|
|
1468
1468
|
|
|
1469
|
-
|
|
1470
|
-
warning.emitted.delete(deprecationCode)
|
|
1469
|
+
FSTDEP010.emitted = false
|
|
1471
1470
|
|
|
1472
1471
|
process.removeAllListeners('warning')
|
|
1473
1472
|
process.on('warning', onWarning)
|
|
1474
1473
|
function onWarning (warning) {
|
|
1475
|
-
t.equal(warning.name, '
|
|
1476
|
-
t.equal(warning.code,
|
|
1474
|
+
t.equal(warning.name, 'DeprecationWarning')
|
|
1475
|
+
t.equal(warning.code, FSTDEP010.code)
|
|
1477
1476
|
}
|
|
1478
1477
|
|
|
1479
1478
|
fastify.get('/', (req, reply) => {
|
|
@@ -1494,14 +1493,13 @@ test('should emit deprecation warning when trying to use the reply.context.confi
|
|
|
1494
1493
|
t.plan(4)
|
|
1495
1494
|
const fastify = Fastify()
|
|
1496
1495
|
|
|
1497
|
-
|
|
1498
|
-
warning.emitted.delete(deprecationCode)
|
|
1496
|
+
FSTDEP019.emitted = false
|
|
1499
1497
|
|
|
1500
1498
|
process.removeAllListeners('warning')
|
|
1501
1499
|
process.on('warning', onWarning)
|
|
1502
1500
|
function onWarning (warning) {
|
|
1503
|
-
t.equal(warning.name, '
|
|
1504
|
-
t.equal(warning.code,
|
|
1501
|
+
t.equal(warning.name, 'DeprecationWarning')
|
|
1502
|
+
t.equal(warning.code, FSTDEP019.code)
|
|
1505
1503
|
}
|
|
1506
1504
|
|
|
1507
1505
|
fastify.get('/', (req, reply) => {
|
|
@@ -2148,3 +2146,29 @@ test('reply.send will intercept ERR_HTTP_HEADERS_SENT and log an error message',
|
|
|
2148
2146
|
t.equal(err.code, 'ERR_HTTP_HEADERS_SENT')
|
|
2149
2147
|
}
|
|
2150
2148
|
})
|
|
2149
|
+
|
|
2150
|
+
test('Uint8Array view of ArrayBuffer returns correct byteLength', t => {
|
|
2151
|
+
t.plan(5)
|
|
2152
|
+
const fastify = Fastify()
|
|
2153
|
+
|
|
2154
|
+
const arrBuf = new ArrayBuffer(100)
|
|
2155
|
+
const arrView = new Uint8Array(arrBuf, 0, 10)
|
|
2156
|
+
fastify.get('/', function (req, reply) {
|
|
2157
|
+
return reply.send(arrView)
|
|
2158
|
+
})
|
|
2159
|
+
|
|
2160
|
+
fastify.listen({ port: 0 }, err => {
|
|
2161
|
+
t.error(err)
|
|
2162
|
+
t.teardown(fastify.close.bind(fastify))
|
|
2163
|
+
|
|
2164
|
+
fastify.inject({
|
|
2165
|
+
method: 'GET',
|
|
2166
|
+
url: '/'
|
|
2167
|
+
}, (err, response) => {
|
|
2168
|
+
t.error(err)
|
|
2169
|
+
t.equal(response.headers['content-type'], 'application/octet-stream')
|
|
2170
|
+
t.equal(response.headers['content-length'], '10')
|
|
2171
|
+
t.same(response.rawPayload.byteLength, arrView.byteLength)
|
|
2172
|
+
})
|
|
2173
|
+
})
|
|
2174
|
+
})
|
|
@@ -151,7 +151,8 @@ t.test('logger instantiation', (t) => {
|
|
|
151
151
|
]
|
|
152
152
|
|
|
153
153
|
const { file, cleanup } = createTempFile(t)
|
|
154
|
-
|
|
154
|
+
// 0600 permissions (read/write for owner only)
|
|
155
|
+
if (process.env.CITGM) { fs.writeFileSync(file, '', { mode: 0o600 }) }
|
|
155
156
|
|
|
156
157
|
const fastify = Fastify({
|
|
157
158
|
logger: { file }
|
package/test/plugin.4.test.js
CHANGED
|
@@ -414,3 +414,50 @@ test('hasPlugin returns true when using encapsulation', async t => {
|
|
|
414
414
|
|
|
415
415
|
await fastify.ready()
|
|
416
416
|
})
|
|
417
|
+
|
|
418
|
+
test('registering plugins with mixed style should return a warning', async t => {
|
|
419
|
+
t.plan(12)
|
|
420
|
+
|
|
421
|
+
const pluginNames = ['error-plugin', 'anonymous', 'anotherPlugin', 'anotherPluginNamed']
|
|
422
|
+
|
|
423
|
+
const oldWarnings = process.listeners('warning')
|
|
424
|
+
process.removeAllListeners('warning')
|
|
425
|
+
process.on('warning', onWarning)
|
|
426
|
+
function onWarning (warning) {
|
|
427
|
+
t.match(warning.message, new RegExp(`.*${pluginNames.shift()} plugin being registered mixes async and callback styles.*`))
|
|
428
|
+
t.equal(warning.name, 'FastifyWarning')
|
|
429
|
+
t.equal(warning.code, 'FSTWRN002')
|
|
430
|
+
}
|
|
431
|
+
t.teardown(() => {
|
|
432
|
+
process.removeListener('warning', onWarning)
|
|
433
|
+
for (const warning of oldWarnings) {
|
|
434
|
+
process.on('warning', warning)
|
|
435
|
+
}
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
const fastify = Fastify()
|
|
439
|
+
|
|
440
|
+
const pluginName = 'error-plugin'
|
|
441
|
+
const errorPlugin = async (app, opts, done) => {
|
|
442
|
+
done()
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const namedPlugin = fp(errorPlugin, { name: pluginName })
|
|
446
|
+
|
|
447
|
+
async function anotherPlugin (app, opts, done) {
|
|
448
|
+
done()
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const anotherPluginNamed = async function (app, opts, done) {
|
|
452
|
+
done()
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
fastify.register(namedPlugin)
|
|
456
|
+
fastify.register(async (app, opts, done) => {
|
|
457
|
+
done()
|
|
458
|
+
})
|
|
459
|
+
fastify.register(anotherPlugin)
|
|
460
|
+
fastify.register(anotherPluginNamed)
|
|
461
|
+
|
|
462
|
+
await fastify.ready()
|
|
463
|
+
})
|
package/test/register.test.js
CHANGED
|
@@ -105,20 +105,20 @@ test('awaitable register and after', async t => {
|
|
|
105
105
|
let second = false
|
|
106
106
|
let third = false
|
|
107
107
|
|
|
108
|
-
await fastify.register(async (instance, opts
|
|
108
|
+
await fastify.register(async (instance, opts) => {
|
|
109
109
|
first = true
|
|
110
110
|
})
|
|
111
111
|
|
|
112
112
|
t.equal(first, true)
|
|
113
113
|
|
|
114
|
-
fastify.register(async (instance, opts
|
|
114
|
+
fastify.register(async (instance, opts) => {
|
|
115
115
|
second = true
|
|
116
116
|
})
|
|
117
117
|
|
|
118
118
|
await fastify.after()
|
|
119
119
|
t.equal(second, true)
|
|
120
120
|
|
|
121
|
-
fastify.register(async (instance, opts
|
|
121
|
+
fastify.register(async (instance, opts) => {
|
|
122
122
|
third = true
|
|
123
123
|
})
|
|
124
124
|
|
|
@@ -145,7 +145,7 @@ test('awaitable register error handling', async t => {
|
|
|
145
145
|
|
|
146
146
|
await t.rejects(fastify.after(), e)
|
|
147
147
|
|
|
148
|
-
fastify.register(async (instance, opts
|
|
148
|
+
fastify.register(async (instance, opts) => {
|
|
149
149
|
t.fail('should not be executed')
|
|
150
150
|
})
|
|
151
151
|
|
|
@@ -167,7 +167,7 @@ test('awaitable after error handling', async t => {
|
|
|
167
167
|
|
|
168
168
|
await t.rejects(fastify.after(), e)
|
|
169
169
|
|
|
170
|
-
fastify.register(async (instance, opts
|
|
170
|
+
fastify.register(async (instance, opts) => {
|
|
171
171
|
t.fail('should not be executed')
|
|
172
172
|
})
|
|
173
173
|
|
|
@@ -200,7 +200,7 @@ test('should emit deprecation warning when using direct return', t => {
|
|
|
200
200
|
|
|
201
201
|
process.on('warning', onWarning)
|
|
202
202
|
function onWarning (warning) {
|
|
203
|
-
t.equal(warning.name, '
|
|
203
|
+
t.equal(warning.name, 'DeprecationWarning')
|
|
204
204
|
t.equal(warning.code, 'FSTDEP013')
|
|
205
205
|
}
|
|
206
206
|
t.teardown(() => process.removeListener('warning', onWarning))
|
package/test/route.7.test.js
CHANGED
|
@@ -178,14 +178,15 @@ test('Set a custom HEAD route before GET one without disabling exposeHeadRoutes
|
|
|
178
178
|
test('Set a custom HEAD route before GET one without disabling exposeHeadRoutes (route)', t => {
|
|
179
179
|
t.plan(7)
|
|
180
180
|
|
|
181
|
-
function onWarning (
|
|
182
|
-
t.
|
|
183
|
-
}
|
|
184
|
-
const warning = {
|
|
185
|
-
emit: onWarning
|
|
181
|
+
function onWarning () {
|
|
182
|
+
t.pass('warning emitted')
|
|
186
183
|
}
|
|
187
184
|
|
|
188
|
-
const route = proxyquire('../lib/route', {
|
|
185
|
+
const route = proxyquire('../lib/route', {
|
|
186
|
+
'./warnings': {
|
|
187
|
+
FSTDEP007: onWarning
|
|
188
|
+
}
|
|
189
|
+
})
|
|
189
190
|
const fastify = proxyquire('..', { './lib/route.js': route })()
|
|
190
191
|
|
|
191
192
|
const resBuffer = Buffer.from('I am a coffee!')
|
|
@@ -540,7 +540,7 @@ test('should be able to handle formats of ajv-formats when added by plugins opti
|
|
|
540
540
|
method: 'POST',
|
|
541
541
|
payload: {
|
|
542
542
|
id: '254381a5-888c-4b41-8116-e3b1a54980bd',
|
|
543
|
-
email: 'info@fastify.
|
|
543
|
+
email: 'info@fastify.dev'
|
|
544
544
|
},
|
|
545
545
|
url: '/'
|
|
546
546
|
}, (_err, res) => {
|
|
@@ -552,7 +552,7 @@ test('should be able to handle formats of ajv-formats when added by plugins opti
|
|
|
552
552
|
method: 'POST',
|
|
553
553
|
payload: {
|
|
554
554
|
id: 'invalid',
|
|
555
|
-
email: 'info@fastify.
|
|
555
|
+
email: 'info@fastify.dev'
|
|
556
556
|
},
|
|
557
557
|
url: '/'
|
|
558
558
|
}, (_err, res) => {
|
|
@@ -6,7 +6,7 @@ const fp = require('fastify-plugin')
|
|
|
6
6
|
const deepClone = require('rfdc')({ circles: true, proto: false })
|
|
7
7
|
const Ajv = require('ajv')
|
|
8
8
|
const { kSchemaController } = require('../lib/symbols.js')
|
|
9
|
-
const
|
|
9
|
+
const { FSTWRN001 } = require('../lib/warnings')
|
|
10
10
|
|
|
11
11
|
const echoParams = (req, reply) => { reply.send(req.params) }
|
|
12
12
|
const echoBody = (req, reply) => { reply.send(req.body) }
|
|
@@ -261,12 +261,12 @@ test('Should emit warning if the schema headers is undefined', t => {
|
|
|
261
261
|
process.on('warning', onWarning)
|
|
262
262
|
function onWarning (warning) {
|
|
263
263
|
t.equal(warning.name, 'FastifyWarning')
|
|
264
|
-
t.equal(warning.code,
|
|
264
|
+
t.equal(warning.code, FSTWRN001.code)
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
t.teardown(() => {
|
|
268
268
|
process.removeListener('warning', onWarning)
|
|
269
|
-
|
|
269
|
+
FSTWRN001.emitted = false
|
|
270
270
|
})
|
|
271
271
|
|
|
272
272
|
fastify.post('/:id', {
|
|
@@ -292,12 +292,12 @@ test('Should emit warning if the schema body is undefined', t => {
|
|
|
292
292
|
process.on('warning', onWarning)
|
|
293
293
|
function onWarning (warning) {
|
|
294
294
|
t.equal(warning.name, 'FastifyWarning')
|
|
295
|
-
t.equal(warning.code,
|
|
295
|
+
t.equal(warning.code, FSTWRN001.code)
|
|
296
296
|
}
|
|
297
297
|
|
|
298
298
|
t.teardown(() => {
|
|
299
299
|
process.removeListener('warning', onWarning)
|
|
300
|
-
|
|
300
|
+
FSTWRN001.emitted = false
|
|
301
301
|
})
|
|
302
302
|
|
|
303
303
|
fastify.post('/:id', {
|
|
@@ -323,12 +323,12 @@ test('Should emit warning if the schema query is undefined', t => {
|
|
|
323
323
|
process.on('warning', onWarning)
|
|
324
324
|
function onWarning (warning) {
|
|
325
325
|
t.equal(warning.name, 'FastifyWarning')
|
|
326
|
-
t.equal(warning.code,
|
|
326
|
+
t.equal(warning.code, FSTWRN001.code)
|
|
327
327
|
}
|
|
328
328
|
|
|
329
329
|
t.teardown(() => {
|
|
330
330
|
process.removeListener('warning', onWarning)
|
|
331
|
-
|
|
331
|
+
FSTWRN001.emitted = false
|
|
332
332
|
})
|
|
333
333
|
|
|
334
334
|
fastify.post('/:id', {
|
|
@@ -354,12 +354,12 @@ test('Should emit warning if the schema params is undefined', t => {
|
|
|
354
354
|
process.on('warning', onWarning)
|
|
355
355
|
function onWarning (warning) {
|
|
356
356
|
t.equal(warning.name, 'FastifyWarning')
|
|
357
|
-
t.equal(warning.code,
|
|
357
|
+
t.equal(warning.code, FSTWRN001.code)
|
|
358
358
|
}
|
|
359
359
|
|
|
360
360
|
t.teardown(() => {
|
|
361
361
|
process.removeListener('warning', onWarning)
|
|
362
|
-
|
|
362
|
+
FSTWRN001.emitted = false
|
|
363
363
|
})
|
|
364
364
|
|
|
365
365
|
fastify.post('/:id', {
|
|
@@ -390,14 +390,14 @@ test('Should emit a warning for every route with undefined schema', t => {
|
|
|
390
390
|
// => 3 x 4 assertions = 12 assertions
|
|
391
391
|
function onWarning (warning) {
|
|
392
392
|
t.equal(warning.name, 'FastifyWarning')
|
|
393
|
-
t.equal(warning.code,
|
|
393
|
+
t.equal(warning.code, FSTWRN001.code)
|
|
394
394
|
t.equal(runs++, expectedWarningEmitted.shift())
|
|
395
395
|
}
|
|
396
396
|
|
|
397
397
|
process.on('warning', onWarning)
|
|
398
398
|
t.teardown(() => {
|
|
399
399
|
process.removeListener('warning', onWarning)
|
|
400
|
-
|
|
400
|
+
FSTWRN001.emitted = false
|
|
401
401
|
})
|
|
402
402
|
|
|
403
403
|
fastify.get('/undefinedParams/:id', {
|
package/test/server.test.js
CHANGED
|
@@ -4,6 +4,7 @@ const t = require('tap')
|
|
|
4
4
|
const test = t.test
|
|
5
5
|
const Fastify = require('..')
|
|
6
6
|
const semver = require('semver')
|
|
7
|
+
const undici = require('undici')
|
|
7
8
|
|
|
8
9
|
test('listen should accept null port', t => {
|
|
9
10
|
t.plan(1)
|
|
@@ -123,3 +124,53 @@ test('abort signal', { skip: semver.lt(process.version, '16.0.0') }, t => {
|
|
|
123
124
|
|
|
124
125
|
t.end()
|
|
125
126
|
})
|
|
127
|
+
|
|
128
|
+
t.test('#5180 - preClose should be called before closing secondary server', t => {
|
|
129
|
+
t.plan(2)
|
|
130
|
+
const fastify = Fastify({ forceCloseConnections: true })
|
|
131
|
+
let flag = false
|
|
132
|
+
t.teardown(fastify.close.bind(fastify))
|
|
133
|
+
|
|
134
|
+
fastify.addHook('preClose', async () => {
|
|
135
|
+
flag = true
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
fastify.get('/', async (req, reply) => {
|
|
139
|
+
await new Promise((resolve) => {
|
|
140
|
+
setTimeout(() => resolve(1), 1000)
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
return { hello: 'world' }
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
fastify.listen({ port: 0 }, (err) => {
|
|
147
|
+
t.error(err)
|
|
148
|
+
const addresses = fastify.addresses()
|
|
149
|
+
const mainServerAddress = fastify.server.address()
|
|
150
|
+
let secondaryAddress
|
|
151
|
+
for (const addr of addresses) {
|
|
152
|
+
if (addr.family !== mainServerAddress.family) {
|
|
153
|
+
secondaryAddress = addr
|
|
154
|
+
secondaryAddress.address = secondaryAddress.family === 'IPv6'
|
|
155
|
+
? `[${secondaryAddress.address}]`
|
|
156
|
+
: secondaryAddress.address
|
|
157
|
+
break
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!secondaryAddress) {
|
|
162
|
+
t.pass('no secondary server')
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
undici.request(`http://${secondaryAddress.address}:${secondaryAddress.port}/`)
|
|
167
|
+
.then(
|
|
168
|
+
() => { t.fail('Request should not succeed') },
|
|
169
|
+
() => { t.ok(flag) }
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
setTimeout(() => {
|
|
173
|
+
fastify.close()
|
|
174
|
+
}, 250)
|
|
175
|
+
})
|
|
176
|
+
})
|
|
@@ -14,7 +14,7 @@ import fastify, {
|
|
|
14
14
|
RegisterOptions,
|
|
15
15
|
RouteOptions
|
|
16
16
|
} from '../../fastify'
|
|
17
|
-
import { RequestPayload, preHandlerAsyncHookHandler } from '../../types/hooks'
|
|
17
|
+
import { DoneFuncWithErrOrRes, HookHandlerDoneFunction, RequestPayload, preHandlerAsyncHookHandler } from '../../types/hooks'
|
|
18
18
|
import { FastifyRouteConfig, RouteGenericInterface } from '../../types/route'
|
|
19
19
|
|
|
20
20
|
const server = fastify()
|
|
@@ -392,6 +392,129 @@ server.route<RouteGenericInterface, CustomContextConfig>({
|
|
|
392
392
|
}
|
|
393
393
|
})
|
|
394
394
|
|
|
395
|
+
server.route({
|
|
396
|
+
method: 'GET',
|
|
397
|
+
url: '/',
|
|
398
|
+
handler: (request, reply) => {
|
|
399
|
+
expectType<FastifyRequest>(request)
|
|
400
|
+
expectType<FastifyReply>(reply)
|
|
401
|
+
},
|
|
402
|
+
onRequest: (request, reply, done) => {
|
|
403
|
+
expectType<FastifyRequest>(request)
|
|
404
|
+
expectType<FastifyReply>(reply)
|
|
405
|
+
expectType<HookHandlerDoneFunction>(done)
|
|
406
|
+
},
|
|
407
|
+
onRequestAbort: (request, done) => {
|
|
408
|
+
expectType<FastifyRequest>(request)
|
|
409
|
+
expectType<HookHandlerDoneFunction>(done)
|
|
410
|
+
},
|
|
411
|
+
preParsing: (request, reply, payload, done) => {
|
|
412
|
+
expectType<FastifyRequest>(request)
|
|
413
|
+
expectType<FastifyReply>(reply)
|
|
414
|
+
expectType<RequestPayload>(payload)
|
|
415
|
+
expectType<<TError extends Error = FastifyError>(err?: TError | null | undefined, res?: RequestPayload | undefined) => void>(done)
|
|
416
|
+
},
|
|
417
|
+
preValidation: (request, reply, done) => {
|
|
418
|
+
expectType<FastifyRequest>(request)
|
|
419
|
+
expectType<FastifyReply>(reply)
|
|
420
|
+
expectType<HookHandlerDoneFunction>(done)
|
|
421
|
+
},
|
|
422
|
+
preHandler: (request, reply, done) => {
|
|
423
|
+
expectType<FastifyRequest>(request)
|
|
424
|
+
expectType<FastifyReply>(reply)
|
|
425
|
+
expectType<HookHandlerDoneFunction>(done)
|
|
426
|
+
},
|
|
427
|
+
preSerialization: (request, reply, payload, done) => {
|
|
428
|
+
expectType<FastifyRequest>(request)
|
|
429
|
+
expectType<FastifyReply>(reply)
|
|
430
|
+
expectType<unknown>(payload)
|
|
431
|
+
expectType<DoneFuncWithErrOrRes>(done)
|
|
432
|
+
},
|
|
433
|
+
onSend: (request, reply, payload, done) => {
|
|
434
|
+
expectType<FastifyRequest>(request)
|
|
435
|
+
expectType<FastifyReply>(reply)
|
|
436
|
+
expectType<unknown>(payload)
|
|
437
|
+
expectType<DoneFuncWithErrOrRes>(done)
|
|
438
|
+
},
|
|
439
|
+
onResponse: (request, reply, done) => {
|
|
440
|
+
expectType<FastifyRequest>(request)
|
|
441
|
+
expectType<FastifyReply>(reply)
|
|
442
|
+
expectType<HookHandlerDoneFunction>(done)
|
|
443
|
+
},
|
|
444
|
+
onTimeout: (request, reply, done) => {
|
|
445
|
+
expectType<FastifyRequest>(request)
|
|
446
|
+
expectType<FastifyReply>(reply)
|
|
447
|
+
expectType<HookHandlerDoneFunction>(done)
|
|
448
|
+
},
|
|
449
|
+
onError: (request, reply, error, done) => {
|
|
450
|
+
expectType<FastifyRequest>(request)
|
|
451
|
+
expectType<FastifyReply>(reply)
|
|
452
|
+
expectType<FastifyError>(error)
|
|
453
|
+
expectType<() => void>(done)
|
|
454
|
+
}
|
|
455
|
+
})
|
|
456
|
+
|
|
457
|
+
server.get('/', {
|
|
458
|
+
onRequest: async (request, reply) => {
|
|
459
|
+
expectType<FastifyRequest>(request)
|
|
460
|
+
expectType<FastifyReply>(reply)
|
|
461
|
+
},
|
|
462
|
+
onRequestAbort: async (request, reply) => {
|
|
463
|
+
expectType<FastifyRequest>(request)
|
|
464
|
+
},
|
|
465
|
+
preParsing: async (request, reply, payload) => {
|
|
466
|
+
expectType<FastifyRequest>(request)
|
|
467
|
+
expectType<FastifyReply>(reply)
|
|
468
|
+
expectType<RequestPayload>(payload)
|
|
469
|
+
},
|
|
470
|
+
preValidation: async (request, reply) => {
|
|
471
|
+
expectType<FastifyRequest>(request)
|
|
472
|
+
expectType<FastifyReply>(reply)
|
|
473
|
+
},
|
|
474
|
+
preHandler: async (request, reply) => {
|
|
475
|
+
expectType<FastifyRequest>(request)
|
|
476
|
+
expectType<FastifyReply>(reply)
|
|
477
|
+
},
|
|
478
|
+
preSerialization: async (request, reply, payload) => {
|
|
479
|
+
expectType<FastifyRequest>(request)
|
|
480
|
+
expectType<FastifyReply>(reply)
|
|
481
|
+
expectType<unknown>(payload)
|
|
482
|
+
},
|
|
483
|
+
onSend: async (request, reply, payload) => {
|
|
484
|
+
expectType<FastifyRequest>(request)
|
|
485
|
+
expectType<FastifyReply>(reply)
|
|
486
|
+
expectType<unknown>(payload)
|
|
487
|
+
},
|
|
488
|
+
onResponse: async (request, reply) => {
|
|
489
|
+
expectType<FastifyRequest>(request)
|
|
490
|
+
expectType<FastifyReply>(reply)
|
|
491
|
+
},
|
|
492
|
+
onTimeout: async (request, reply) => {
|
|
493
|
+
expectType<FastifyRequest>(request)
|
|
494
|
+
expectType<FastifyReply>(reply)
|
|
495
|
+
},
|
|
496
|
+
onError: async (request, reply, error) => {
|
|
497
|
+
expectType<FastifyRequest>(request)
|
|
498
|
+
expectType<FastifyReply>(reply)
|
|
499
|
+
expectType<FastifyError>(error)
|
|
500
|
+
}
|
|
501
|
+
}, async (request, reply) => {
|
|
502
|
+
expectType<FastifyRequest>(request)
|
|
503
|
+
expectType<FastifyReply>(reply)
|
|
504
|
+
})
|
|
505
|
+
|
|
506
|
+
// TODO: Should throw errors
|
|
507
|
+
// expectError(server.get('/', { onRequest: async (request, reply, done) => {} }, async (request, reply) => {}))
|
|
508
|
+
// expectError(server.get('/', { onRequestAbort: async (request, done) => {} }, async (request, reply) => {}))
|
|
509
|
+
// expectError(server.get('/', { preParsing: async (request, reply, payload, done) => {} }, async (request, reply) => {}))
|
|
510
|
+
// expectError(server.get('/', { preValidation: async (request, reply, done) => {} }, async (request, reply) => {}))
|
|
511
|
+
// expectError(server.get('/', { preHandler: async (request, reply, done) => {} }, async (request, reply) => {}))
|
|
512
|
+
// expectError(server.get('/', { preSerialization: async (request, reply, payload, done) => {} }, async (request, reply) => {}))
|
|
513
|
+
// expectError(server.get('/', { onSend: async (request, reply, payload, done) => {} }, async (request, reply) => {}))
|
|
514
|
+
// expectError(server.get('/', { onResponse: async (request, reply, done) => {} }, async (request, reply) => {}))
|
|
515
|
+
// expectError(server.get('/', { onTimeout: async (request, reply, done) => {} }, async (request, reply) => {}))
|
|
516
|
+
// expectError(server.get('/', { onError: async (request, reply, error, done) => {} }, async (request, reply) => {}))
|
|
517
|
+
|
|
395
518
|
server.addHook('preClose', function (done) {
|
|
396
519
|
expectType<FastifyInstance>(this)
|
|
397
520
|
expectAssignable<(err?: FastifyError) => void>(done)
|
|
@@ -256,6 +256,18 @@ expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42 },
|
|
|
256
256
|
expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42, exclusive: true }, () => {}))
|
|
257
257
|
expectNotDeprecated(server.listen({ port: 3000, host: '::/0', ipv6Only: true }, () => {}))
|
|
258
258
|
|
|
259
|
+
// test after method
|
|
260
|
+
expectAssignable<FastifyInstance>(server.after())
|
|
261
|
+
expectAssignable<FastifyInstance>(server.after((err) => {
|
|
262
|
+
expectType<Error | null>(err)
|
|
263
|
+
}))
|
|
264
|
+
|
|
265
|
+
// test ready method
|
|
266
|
+
expectAssignable<FastifyInstance>(server.ready())
|
|
267
|
+
expectAssignable<FastifyInstance>(server.ready((err) => {
|
|
268
|
+
expectType<Error | null>(err)
|
|
269
|
+
}))
|
|
270
|
+
|
|
259
271
|
expectAssignable<void>(server.routing({} as RawRequestDefaultExpression, {} as RawReplyDefaultExpression))
|
|
260
272
|
|
|
261
273
|
expectType<FastifyInstance>(fastify().get<RouteGenericInterface, { contextKey: string }>('/', {
|
|
@@ -74,6 +74,20 @@ P.Logger
|
|
|
74
74
|
|
|
75
75
|
expectType<P.Logger>(serverWithPino.log)
|
|
76
76
|
|
|
77
|
+
serverWithPino.route({
|
|
78
|
+
method: 'GET',
|
|
79
|
+
url: '/',
|
|
80
|
+
handler (request) {
|
|
81
|
+
expectType<P.Logger>(this.log)
|
|
82
|
+
expectType<P.Logger>(request.log)
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
serverWithPino.get('/', function (request) {
|
|
87
|
+
expectType<P.Logger>(this.log)
|
|
88
|
+
expectType<P.Logger>(request.log)
|
|
89
|
+
})
|
|
90
|
+
|
|
77
91
|
const serverWithLogOptions = fastify<
|
|
78
92
|
Server,
|
|
79
93
|
IncomingMessage,
|