fastify 6.0.0-alpha.2 → 6.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/Guides/Ecosystem.md +2 -5
- package/docs/Guides/Style-Guide.md +6 -5
- package/docs/Reference/ContentTypeParser.md +23 -1
- package/docs/Reference/Validation-and-Serialization.md +11 -0
- package/docs/Reference/Warnings.md +10 -0
- package/fastify.js +1 -1
- package/lib/four-oh-four.js +10 -22
- package/lib/route.js +7 -4
- package/lib/schemas.js +5 -2
- package/lib/validation.js +196 -23
- package/lib/warnings.js +10 -1
- package/package.json +1 -1
- package/test/404s.test.js +105 -7
- package/test/router-options.test.js +24 -0
- package/test/schema-feature.test.js +158 -0
- package/test/schema-special-usage.test.js +81 -0
- package/test/schema-validation.test.js +378 -0
- package/test/types/logger.tst.ts +6 -0
- package/.pi/self-learning-memory/README.md +0 -8
- package/.pi/self-learning-memory/core/CORE.md +0 -33
- package/.pi/self-learning-memory/core/index.json +0 -735
- package/.pi/self-learning-memory/daily/2026-07-06.md +0 -22
- package/.pi/self-learning-memory/daily/2026-07-29.md +0 -50
- package/.pi/self-learning-memory/daily/2026-08-04.md +0 -41
- package/.pi/self-learning-memory/daily/2026-08-18.md +0 -40
- package/.pi/self-learning-memory/long-term-memory.md +0 -89
- package/AGENTS.md +0 -290
package/test/404s.test.js
CHANGED
|
@@ -1226,7 +1226,7 @@ test('onSend hooks run when an encapsulated route invokes the notFound handler',
|
|
|
1226
1226
|
|
|
1227
1227
|
// https://github.com/fastify/fastify/issues/713
|
|
1228
1228
|
test('preHandler option for setNotFoundHandler', async t => {
|
|
1229
|
-
t.plan(
|
|
1229
|
+
t.plan(11)
|
|
1230
1230
|
|
|
1231
1231
|
await t.test('preHandler option', (t, done) => {
|
|
1232
1232
|
t.plan(2)
|
|
@@ -1283,6 +1283,39 @@ test('preHandler option for setNotFoundHandler', async t => {
|
|
|
1283
1283
|
})
|
|
1284
1284
|
})
|
|
1285
1285
|
|
|
1286
|
+
// https://github.com/fastify/fastify/security/advisories/GHSA-gm8r-x7h4-fm5r
|
|
1287
|
+
await t.test('preHandler hook in setNotFoundHandler should be called when callNotFound and the route is registered first', (t, done) => {
|
|
1288
|
+
t.plan(3)
|
|
1289
|
+
const fastify = Fastify()
|
|
1290
|
+
|
|
1291
|
+
// Register the route before the not-found handler so that the route's
|
|
1292
|
+
// preReady callback snapshots the not-found context before its lifecycle
|
|
1293
|
+
// hooks are populated.
|
|
1294
|
+
fastify.post('/', function (req, reply) {
|
|
1295
|
+
t.assert.strictEqual(reply.callNotFound(), reply)
|
|
1296
|
+
})
|
|
1297
|
+
|
|
1298
|
+
fastify.setNotFoundHandler({
|
|
1299
|
+
preHandler: (req, reply, done) => {
|
|
1300
|
+
req.body.preHandler = true
|
|
1301
|
+
done()
|
|
1302
|
+
}
|
|
1303
|
+
}, function (req, reply) {
|
|
1304
|
+
reply.code(404).send(req.body)
|
|
1305
|
+
})
|
|
1306
|
+
|
|
1307
|
+
fastify.inject({
|
|
1308
|
+
method: 'POST',
|
|
1309
|
+
url: '/',
|
|
1310
|
+
payload: { hello: 'world' }
|
|
1311
|
+
}, (err, res) => {
|
|
1312
|
+
t.assert.ifError(err)
|
|
1313
|
+
const payload = JSON.parse(res.payload)
|
|
1314
|
+
t.assert.deepStrictEqual(payload, { preHandler: true, hello: 'world' })
|
|
1315
|
+
done()
|
|
1316
|
+
})
|
|
1317
|
+
})
|
|
1318
|
+
|
|
1286
1319
|
await t.test('preHandler hook in setNotFoundHandler should accept an array of functions and be called when callNotFound', (t, done) => {
|
|
1287
1320
|
t.plan(2)
|
|
1288
1321
|
const fastify = Fastify()
|
|
@@ -1800,11 +1833,12 @@ test('400 in case of bad url (pre find-my-way v2.2.0 was a 404)', async t => {
|
|
|
1800
1833
|
method: 'GET'
|
|
1801
1834
|
}, (err, response) => {
|
|
1802
1835
|
t.assert.ifError(err)
|
|
1803
|
-
t.assert.strictEqual(response.statusCode,
|
|
1836
|
+
t.assert.strictEqual(response.statusCode, 400)
|
|
1804
1837
|
t.assert.deepStrictEqual(JSON.parse(response.payload), {
|
|
1805
|
-
error: '
|
|
1806
|
-
message: '
|
|
1807
|
-
statusCode:
|
|
1838
|
+
error: 'Bad Request',
|
|
1839
|
+
message: "'/%c0' is not a valid url component",
|
|
1840
|
+
statusCode: 400,
|
|
1841
|
+
code: 'FST_ERR_BAD_URL'
|
|
1808
1842
|
})
|
|
1809
1843
|
done()
|
|
1810
1844
|
})
|
|
@@ -1840,12 +1874,76 @@ test('400 in case of bad url (pre find-my-way v2.2.0 was a 404)', async t => {
|
|
|
1840
1874
|
method: 'GET'
|
|
1841
1875
|
}, (err, response) => {
|
|
1842
1876
|
t.assert.ifError(err)
|
|
1843
|
-
t.assert.strictEqual(response.statusCode,
|
|
1844
|
-
t.assert.deepStrictEqual(response.payload,
|
|
1877
|
+
t.assert.strictEqual(response.statusCode, 400)
|
|
1878
|
+
t.assert.deepStrictEqual(JSON.parse(response.payload), {
|
|
1879
|
+
error: 'Bad Request',
|
|
1880
|
+
message: "'/%c0' is not a valid url component",
|
|
1881
|
+
statusCode: 400,
|
|
1882
|
+
code: 'FST_ERR_BAD_URL'
|
|
1883
|
+
})
|
|
1845
1884
|
done()
|
|
1846
1885
|
})
|
|
1847
1886
|
})
|
|
1848
1887
|
|
|
1888
|
+
await t.test('Bad URL does not invoke an encapsulated not found handler', async t => {
|
|
1889
|
+
const fastify = Fastify()
|
|
1890
|
+
let publicHandlerCalls = 0
|
|
1891
|
+
let privatePreHandlerCalls = 0
|
|
1892
|
+
let privateHandlerCalls = 0
|
|
1893
|
+
|
|
1894
|
+
fastify.register(async function (instance) {
|
|
1895
|
+
instance.get('/existing', () => 'public')
|
|
1896
|
+
instance.setNotFoundHandler(function (_request, reply) {
|
|
1897
|
+
publicHandlerCalls++
|
|
1898
|
+
reply.code(404).send('public not found')
|
|
1899
|
+
})
|
|
1900
|
+
}, { prefix: '/public' })
|
|
1901
|
+
|
|
1902
|
+
fastify.register(async function (instance) {
|
|
1903
|
+
instance.setNotFoundHandler({
|
|
1904
|
+
preHandler: function (request, reply, done) {
|
|
1905
|
+
privatePreHandlerCalls++
|
|
1906
|
+
if (request.headers.authorization !== 'Bearer valid') {
|
|
1907
|
+
reply.code(401).send('unauthorized')
|
|
1908
|
+
}
|
|
1909
|
+
done()
|
|
1910
|
+
}
|
|
1911
|
+
}, function (_request, reply) {
|
|
1912
|
+
privateHandlerCalls++
|
|
1913
|
+
reply.send('private canary')
|
|
1914
|
+
})
|
|
1915
|
+
}, { prefix: '/private' })
|
|
1916
|
+
|
|
1917
|
+
const malformed = await fastify.inject({
|
|
1918
|
+
method: 'DELETE',
|
|
1919
|
+
url: '/public/%c0'
|
|
1920
|
+
})
|
|
1921
|
+
t.assert.strictEqual(malformed.statusCode, 400)
|
|
1922
|
+
t.assert.strictEqual(JSON.parse(malformed.payload).code, 'FST_ERR_BAD_URL')
|
|
1923
|
+
t.assert.strictEqual(publicHandlerCalls, 0)
|
|
1924
|
+
t.assert.strictEqual(privatePreHandlerCalls, 0)
|
|
1925
|
+
t.assert.strictEqual(privateHandlerCalls, 0)
|
|
1926
|
+
|
|
1927
|
+
const unauthorized = await fastify.inject({
|
|
1928
|
+
method: 'DELETE',
|
|
1929
|
+
url: '/private/missing'
|
|
1930
|
+
})
|
|
1931
|
+
t.assert.strictEqual(unauthorized.statusCode, 401)
|
|
1932
|
+
t.assert.strictEqual(unauthorized.payload, 'unauthorized')
|
|
1933
|
+
t.assert.strictEqual(privatePreHandlerCalls, 1)
|
|
1934
|
+
t.assert.strictEqual(privateHandlerCalls, 0)
|
|
1935
|
+
|
|
1936
|
+
const authorized = await fastify.inject({
|
|
1937
|
+
method: 'DELETE',
|
|
1938
|
+
url: '/private/missing',
|
|
1939
|
+
headers: { authorization: 'Bearer valid' }
|
|
1940
|
+
})
|
|
1941
|
+
t.assert.strictEqual(authorized.statusCode, 200)
|
|
1942
|
+
t.assert.strictEqual(authorized.payload, 'private canary')
|
|
1943
|
+
t.assert.strictEqual(privatePreHandlerCalls, 2)
|
|
1944
|
+
t.assert.strictEqual(privateHandlerCalls, 1)
|
|
1945
|
+
})
|
|
1946
|
+
|
|
1849
1947
|
await t.test('Bad URL with special characters should be properly JSON escaped', (t, done) => {
|
|
1850
1948
|
t.plan(3)
|
|
1851
1949
|
const fastify = Fastify()
|
|
@@ -469,6 +469,30 @@ test('Should honor routerOptions.onBadUrl', async t => {
|
|
|
469
469
|
t.assert.strictEqual(res.payload, 'Bad URL: /hello/%world')
|
|
470
470
|
})
|
|
471
471
|
|
|
472
|
+
test('Should honor routerOptions.onBadUrl when no method tree exists', async t => {
|
|
473
|
+
t.plan(3)
|
|
474
|
+
const fastify = Fastify({
|
|
475
|
+
routerOptions: {
|
|
476
|
+
onBadUrl: function (path, _, res) {
|
|
477
|
+
t.assert.ok('bad url called')
|
|
478
|
+
res.statusCode = 400
|
|
479
|
+
res.end(`Bad URL: ${path}`)
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
})
|
|
483
|
+
|
|
484
|
+
fastify.get('/hello/:id', (req, res) => {
|
|
485
|
+
res.send({ hello: 'world' })
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
const res = await fastify.inject({
|
|
489
|
+
method: 'DELETE',
|
|
490
|
+
url: '/hello/%world'
|
|
491
|
+
})
|
|
492
|
+
t.assert.strictEqual(res.statusCode, 400)
|
|
493
|
+
t.assert.strictEqual(res.payload, 'Bad URL: /hello/%world')
|
|
494
|
+
})
|
|
495
|
+
|
|
472
496
|
test('Should honor routerOptions.onMaxParamLength', async t => {
|
|
473
497
|
t.plan(3)
|
|
474
498
|
const fastify = Fastify({
|
|
@@ -471,6 +471,164 @@ test('Should emit a warning for every route with undefined schema', (t, testDone
|
|
|
471
471
|
})
|
|
472
472
|
})
|
|
473
473
|
|
|
474
|
+
test('Default validator compiler is initialized for a route whose only schema is false', async (t) => {
|
|
475
|
+
t.plan(2)
|
|
476
|
+
const fastify = Fastify({ exposeHeadRoutes: false })
|
|
477
|
+
|
|
478
|
+
fastify.post('/body', {
|
|
479
|
+
handler: echoBody,
|
|
480
|
+
schema: {
|
|
481
|
+
body: false
|
|
482
|
+
}
|
|
483
|
+
})
|
|
484
|
+
|
|
485
|
+
const res = await fastify.inject({
|
|
486
|
+
method: 'POST',
|
|
487
|
+
url: '/body',
|
|
488
|
+
payload: {}
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
t.assert.strictEqual(res.statusCode, 400)
|
|
492
|
+
t.assert.ok(fastify.validatorCompiler, 'validator compiler is initialized')
|
|
493
|
+
})
|
|
494
|
+
|
|
495
|
+
test('Boolean false request schemas reject every request and no handler executes', async (t) => {
|
|
496
|
+
t.plan(5)
|
|
497
|
+
const fastify = Fastify({ exposeHeadRoutes: false })
|
|
498
|
+
|
|
499
|
+
let bodyExecuted = false
|
|
500
|
+
let qsExecuted = false
|
|
501
|
+
let paramsExecuted = false
|
|
502
|
+
let headersExecuted = false
|
|
503
|
+
|
|
504
|
+
fastify.post('/body', {
|
|
505
|
+
handler: async () => { bodyExecuted = true; return { protectedActionExecuted: true } },
|
|
506
|
+
schema: { body: false }
|
|
507
|
+
})
|
|
508
|
+
fastify.get('/querystring', {
|
|
509
|
+
handler: async () => { qsExecuted = true; return { protectedActionExecuted: true } },
|
|
510
|
+
schema: { querystring: false }
|
|
511
|
+
})
|
|
512
|
+
fastify.post('/params/:id', {
|
|
513
|
+
handler: async () => { paramsExecuted = true; return { protectedActionExecuted: true } },
|
|
514
|
+
schema: { params: false }
|
|
515
|
+
})
|
|
516
|
+
fastify.post('/headers', {
|
|
517
|
+
handler: async () => { headersExecuted = true; return { protectedActionExecuted: true } },
|
|
518
|
+
schema: { headers: false }
|
|
519
|
+
})
|
|
520
|
+
|
|
521
|
+
const r1 = await fastify.inject({ method: 'POST', url: '/body', payload: {} })
|
|
522
|
+
t.assert.strictEqual(r1.statusCode, 400)
|
|
523
|
+
const r2 = await fastify.inject({ method: 'GET', url: '/querystring' })
|
|
524
|
+
t.assert.strictEqual(r2.statusCode, 400)
|
|
525
|
+
const r3 = await fastify.inject({ method: 'POST', url: '/params/1' })
|
|
526
|
+
t.assert.strictEqual(r3.statusCode, 400)
|
|
527
|
+
const r4 = await fastify.inject({ method: 'POST', url: '/headers' })
|
|
528
|
+
t.assert.strictEqual(r4.statusCode, 400)
|
|
529
|
+
|
|
530
|
+
t.assert.deepStrictEqual({
|
|
531
|
+
bodyExecuted,
|
|
532
|
+
qsExecuted,
|
|
533
|
+
paramsExecuted,
|
|
534
|
+
headersExecuted
|
|
535
|
+
}, {
|
|
536
|
+
bodyExecuted: false,
|
|
537
|
+
qsExecuted: false,
|
|
538
|
+
paramsExecuted: false,
|
|
539
|
+
headersExecuted: false
|
|
540
|
+
})
|
|
541
|
+
})
|
|
542
|
+
|
|
543
|
+
test('Custom validator compiler receives the literal boolean false schema', async (t) => {
|
|
544
|
+
t.plan(3)
|
|
545
|
+
const received = []
|
|
546
|
+
const fastify = Fastify({ exposeHeadRoutes: false })
|
|
547
|
+
|
|
548
|
+
fastify.post('/body', {
|
|
549
|
+
handler: async () => ({ ok: true }),
|
|
550
|
+
schema: { body: false },
|
|
551
|
+
validatorCompiler: ({ schema, httpPart }) => {
|
|
552
|
+
received.push({ schema, httpPart })
|
|
553
|
+
return () => { throw new Error('should not validate') }
|
|
554
|
+
}
|
|
555
|
+
})
|
|
556
|
+
|
|
557
|
+
await fastify.ready()
|
|
558
|
+
t.assert.strictEqual(received.length, 1)
|
|
559
|
+
t.assert.strictEqual(received[0].schema, false)
|
|
560
|
+
t.assert.strictEqual(received[0].httpPart, 'body')
|
|
561
|
+
})
|
|
562
|
+
|
|
563
|
+
test('FSTWRN001 is emitted only for explicitly undefined schemas, not boolean false', async (t) => {
|
|
564
|
+
t.plan(4)
|
|
565
|
+
const spyData = spyWarning(FSTWRN001)
|
|
566
|
+
t.after(spyData.restore)
|
|
567
|
+
|
|
568
|
+
const fastify = Fastify({ exposeHeadRoutes: false })
|
|
569
|
+
|
|
570
|
+
fastify.post('/false-body', {
|
|
571
|
+
handler: async () => ({ ok: true }),
|
|
572
|
+
schema: { body: false }
|
|
573
|
+
})
|
|
574
|
+
fastify.post('/undefined-body', {
|
|
575
|
+
handler: async () => ({ ok: true }),
|
|
576
|
+
schema: { body: undefined }
|
|
577
|
+
})
|
|
578
|
+
|
|
579
|
+
await fastify.ready()
|
|
580
|
+
t.assert.strictEqual(spyData.callCount(), 1)
|
|
581
|
+
t.assert.deepStrictEqual(spyData.calls[0], { arguments: ['body', 'POST', '/undefined-body'], result: true })
|
|
582
|
+
|
|
583
|
+
const r1 = await fastify.inject({ method: 'POST', url: '/false-body', payload: {} })
|
|
584
|
+
t.assert.strictEqual(r1.statusCode, 400)
|
|
585
|
+
const r2 = await fastify.inject({ method: 'POST', url: '/undefined-body', payload: {} })
|
|
586
|
+
t.assert.strictEqual(r2.statusCode, 200)
|
|
587
|
+
})
|
|
588
|
+
|
|
589
|
+
test('Invalid null schema fails closed during schema compilation', async (t) => {
|
|
590
|
+
t.plan(3)
|
|
591
|
+
const fastify = Fastify({ exposeHeadRoutes: false })
|
|
592
|
+
|
|
593
|
+
let handlerExecuted = false
|
|
594
|
+
fastify.post('/null-body', {
|
|
595
|
+
handler: async () => { handlerExecuted = true; return { ok: true } },
|
|
596
|
+
schema: { body: null }
|
|
597
|
+
})
|
|
598
|
+
|
|
599
|
+
await t.assert.rejects(fastify.ready(), (err) => {
|
|
600
|
+
t.assert.strictEqual(err.code, 'FST_ERR_SCH_VALIDATION_BUILD')
|
|
601
|
+
return true
|
|
602
|
+
})
|
|
603
|
+
t.assert.strictEqual(handlerExecuted, false)
|
|
604
|
+
})
|
|
605
|
+
|
|
606
|
+
test('Boolean false request schema via the query alias rejects every request', async (t) => {
|
|
607
|
+
const fastify = Fastify()
|
|
608
|
+
let handlerExecuted = false
|
|
609
|
+
|
|
610
|
+
// `query` is a documented alias for `querystring`; a deny-all `false` must be
|
|
611
|
+
// aliased and enforced just like the canonical key.
|
|
612
|
+
fastify.get('/', {
|
|
613
|
+
handler: async () => { handlerExecuted = true; return { protectedActionExecuted: true } },
|
|
614
|
+
schema: { query: false }
|
|
615
|
+
})
|
|
616
|
+
|
|
617
|
+
const res = await fastify.inject({ method: 'GET', url: '/?x=1' })
|
|
618
|
+
|
|
619
|
+
t.assert.strictEqual(res.statusCode, 400)
|
|
620
|
+
t.assert.strictEqual(handlerExecuted, false)
|
|
621
|
+
})
|
|
622
|
+
|
|
623
|
+
test('Setting both query and querystring still throws (boolean false included)', async (t) => {
|
|
624
|
+
const fastify = Fastify()
|
|
625
|
+
fastify.get('/', {
|
|
626
|
+
handler: async () => ({ ok: true }),
|
|
627
|
+
schema: { query: false, querystring: false }
|
|
628
|
+
})
|
|
629
|
+
await t.assert.rejects(fastify.ready())
|
|
630
|
+
})
|
|
631
|
+
|
|
474
632
|
test('First level $ref', (t, testDone) => {
|
|
475
633
|
t.plan(2)
|
|
476
634
|
const fastify = Fastify()
|
|
@@ -939,6 +939,87 @@ test('Supports async AJV validation', (t, testDone) => {
|
|
|
939
939
|
completion.patience.then(testDone)
|
|
940
940
|
})
|
|
941
941
|
|
|
942
|
+
// @see https://github.com/fastify/fastify/security/advisories/GHSA-667r-xxjv-c9mm
|
|
943
|
+
test('async validation result must not replace the request body (value collision)', async (t) => {
|
|
944
|
+
const fastify = Fastify()
|
|
945
|
+
fastify.post('/', {
|
|
946
|
+
schema: {
|
|
947
|
+
body: {
|
|
948
|
+
$async: true,
|
|
949
|
+
type: 'object',
|
|
950
|
+
additionalProperties: true,
|
|
951
|
+
properties: { hello: { type: 'string' } }
|
|
952
|
+
}
|
|
953
|
+
},
|
|
954
|
+
handler: async (request) => request.body
|
|
955
|
+
})
|
|
956
|
+
|
|
957
|
+
const res = await fastify.inject({
|
|
958
|
+
method: 'POST',
|
|
959
|
+
url: '/',
|
|
960
|
+
headers: { 'content-type': 'application/json' },
|
|
961
|
+
body: JSON.stringify({ hello: 'world', value: { hello: 'evil' } })
|
|
962
|
+
})
|
|
963
|
+
|
|
964
|
+
t.assert.strictEqual(res.statusCode, 200)
|
|
965
|
+
// The validated body must be preserved; a `value` key must NOT replace it.
|
|
966
|
+
t.assert.deepStrictEqual(res.json(), { hello: 'world', value: { hello: 'evil' } })
|
|
967
|
+
})
|
|
968
|
+
|
|
969
|
+
// @see https://github.com/fastify/fastify/security/advisories/GHSA-667r-xxjv-c9mm
|
|
970
|
+
test('async validation result must not be treated as an error (error collision)', async (t) => {
|
|
971
|
+
const fastify = Fastify()
|
|
972
|
+
fastify.post('/', {
|
|
973
|
+
schema: {
|
|
974
|
+
body: {
|
|
975
|
+
$async: true,
|
|
976
|
+
type: 'object',
|
|
977
|
+
additionalProperties: true,
|
|
978
|
+
properties: { hello: { type: 'string' } }
|
|
979
|
+
}
|
|
980
|
+
},
|
|
981
|
+
handler: async (request) => request.body
|
|
982
|
+
})
|
|
983
|
+
|
|
984
|
+
const res = await fastify.inject({
|
|
985
|
+
method: 'POST',
|
|
986
|
+
url: '/',
|
|
987
|
+
headers: { 'content-type': 'application/json' },
|
|
988
|
+
body: JSON.stringify({ hello: 'world', error: 'boom' })
|
|
989
|
+
})
|
|
990
|
+
|
|
991
|
+
// An `error` key in the payload must NOT be treated as a validation failure.
|
|
992
|
+
t.assert.strictEqual(res.statusCode, 200)
|
|
993
|
+
t.assert.deepStrictEqual(res.json(), { hello: 'world', error: 'boom' })
|
|
994
|
+
})
|
|
995
|
+
|
|
996
|
+
test('async custom validator resolving false uses its validation errors', async t => {
|
|
997
|
+
const fastify = Fastify()
|
|
998
|
+
fastify.setValidatorCompiler(() => {
|
|
999
|
+
const validate = () => Promise.resolve(false)
|
|
1000
|
+
validate.errors = [{
|
|
1001
|
+
instancePath: '',
|
|
1002
|
+
schemaPath: '#/custom',
|
|
1003
|
+
keyword: 'custom',
|
|
1004
|
+
params: {},
|
|
1005
|
+
message: 'must pass custom validation'
|
|
1006
|
+
}]
|
|
1007
|
+
return validate
|
|
1008
|
+
})
|
|
1009
|
+
fastify.post('/', {
|
|
1010
|
+
schema: { body: { type: 'object' } }
|
|
1011
|
+
}, async () => ({ ok: true }))
|
|
1012
|
+
|
|
1013
|
+
const res = await fastify.inject({
|
|
1014
|
+
method: 'POST',
|
|
1015
|
+
url: '/',
|
|
1016
|
+
payload: {}
|
|
1017
|
+
})
|
|
1018
|
+
|
|
1019
|
+
t.assert.strictEqual(res.statusCode, 400)
|
|
1020
|
+
t.assert.strictEqual(res.json().code, 'FST_ERR_VALIDATION')
|
|
1021
|
+
})
|
|
1022
|
+
|
|
942
1023
|
test('Check all the async AJV validation paths', async (t) => {
|
|
943
1024
|
const fastify = Fastify({
|
|
944
1025
|
exposeHeadRoutes: false,
|