fastify 3.27.2 → 4.0.0-alpha.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 +5 -4
- package/build/build-error-serializer.js +27 -0
- package/build/build-validation.js +47 -35
- package/docs/Migration-Guide-V4.md +12 -0
- package/docs/Reference/ContentTypeParser.md +4 -0
- package/docs/Reference/Errors.md +51 -6
- package/docs/Reference/Hooks.md +4 -7
- package/docs/Reference/LTS.md +5 -4
- package/docs/Reference/Reply.md +23 -22
- package/docs/Reference/Request.md +1 -3
- package/docs/Reference/Routes.md +17 -10
- package/docs/Reference/Server.md +48 -63
- package/docs/Reference/TypeScript.md +11 -13
- package/docs/Reference/Validation-and-Serialization.md +28 -53
- package/docs/Type-Providers.md +257 -0
- package/examples/hooks.js +1 -1
- package/examples/simple-stream.js +18 -0
- package/fastify.d.ts +34 -22
- package/fastify.js +37 -35
- package/lib/configValidator.js +902 -1023
- package/lib/contentTypeParser.js +6 -16
- package/lib/context.js +36 -10
- package/lib/decorate.js +3 -1
- package/lib/error-handler.js +158 -0
- package/lib/error-serializer.js +257 -0
- package/lib/errors.js +43 -9
- package/lib/fourOhFour.js +31 -20
- package/lib/handleRequest.js +10 -13
- package/lib/hooks.js +14 -9
- package/lib/pluginOverride.js +0 -3
- package/lib/pluginUtils.js +3 -2
- package/lib/reply.js +28 -157
- package/lib/request.js +13 -10
- package/lib/route.js +131 -138
- package/lib/schema-controller.js +2 -2
- package/lib/schemas.js +27 -1
- package/lib/server.js +219 -116
- package/lib/symbols.js +4 -3
- package/lib/validation.js +2 -1
- package/lib/warnings.js +2 -12
- package/lib/wrapThenable.js +4 -11
- package/package.json +31 -35
- package/test/404s.test.js +243 -110
- package/test/500s.test.js +2 -2
- package/test/async-await.test.js +13 -69
- package/test/content-parser.test.js +32 -0
- package/test/context-config.test.js +52 -0
- package/test/custom-http-server.test.js +14 -7
- package/test/custom-parser-async.test.js +0 -65
- package/test/custom-parser.test.js +54 -121
- package/test/decorator.test.js +1 -3
- package/test/delete.test.js +5 -5
- package/test/encapsulated-error-handler.test.js +50 -0
- package/test/esm/index.test.js +0 -14
- package/test/fastify-instance.test.js +4 -4
- package/test/fluent-schema.test.js +4 -4
- package/test/get.test.js +3 -3
- package/test/helper.js +18 -3
- package/test/hooks-async.test.js +14 -47
- package/test/hooks.on-ready.test.js +9 -4
- package/test/hooks.test.js +58 -99
- package/test/http2/closing.test.js +5 -11
- package/test/http2/unknown-http-method.test.js +3 -9
- package/test/https/custom-https-server.test.js +12 -6
- package/test/input-validation.js +2 -2
- package/test/internals/handleRequest.test.js +3 -40
- package/test/internals/initialConfig.test.js +33 -12
- package/test/internals/reply.test.js +245 -3
- package/test/internals/request.test.js +13 -7
- package/test/internals/server.test.js +88 -0
- package/test/listen.test.js +84 -1
- package/test/logger.test.js +80 -40
- package/test/maxRequestsPerSocket.test.js +6 -4
- package/test/middleware.test.js +2 -25
- package/test/nullable-validation.test.js +51 -14
- package/test/plugin.test.js +31 -5
- package/test/pretty-print.test.js +22 -10
- package/test/reply-error.test.js +123 -12
- package/test/request-error.test.js +2 -5
- package/test/route-hooks.test.js +17 -17
- package/test/route-prefix.test.js +2 -1
- package/test/route.test.js +204 -20
- package/test/router-options.test.js +1 -1
- package/test/schema-examples.test.js +11 -5
- package/test/schema-feature.test.js +24 -19
- package/test/schema-serialization.test.js +9 -9
- package/test/schema-special-usage.test.js +14 -81
- package/test/schema-validation.test.js +9 -9
- package/test/skip-reply-send.test.js +1 -1
- package/test/stream.test.js +23 -12
- package/test/throw.test.js +8 -5
- package/test/type-provider.test.js +20 -0
- package/test/types/fastify.test-d.ts +10 -18
- package/test/types/import.js +2 -0
- package/test/types/import.ts +1 -0
- package/test/types/instance.test-d.ts +35 -14
- package/test/types/logger.test-d.ts +44 -15
- package/test/types/route.test-d.ts +8 -2
- package/test/types/schema.test-d.ts +2 -39
- package/test/types/type-provider.test-d.ts +417 -0
- package/test/validation-error-handling.test.js +8 -8
- package/test/versioned-routes.test.js +28 -16
- package/test/wrapThenable.test.js +7 -6
- package/types/content-type-parser.d.ts +17 -8
- package/types/hooks.d.ts +102 -59
- package/types/instance.d.ts +124 -104
- package/types/logger.d.ts +18 -104
- package/types/plugin.d.ts +10 -4
- package/types/reply.d.ts +16 -11
- package/types/request.d.ts +10 -5
- package/types/route.d.ts +42 -31
- package/types/schema.d.ts +1 -1
- package/types/type-provider.d.ts +99 -0
- package/types/utils.d.ts +1 -1
- package/lib/schema-compilers.js +0 -12
- package/test/emit-warning.test.js +0 -166
package/test/route.test.js
CHANGED
|
@@ -5,11 +5,20 @@ const split = require('split2')
|
|
|
5
5
|
const t = require('tap')
|
|
6
6
|
const test = t.test
|
|
7
7
|
const sget = require('simple-get').concat
|
|
8
|
-
const joi = require('
|
|
8
|
+
const joi = require('joi')
|
|
9
9
|
const Fastify = require('..')
|
|
10
10
|
const proxyquire = require('proxyquire')
|
|
11
11
|
const { FST_ERR_INVALID_URL } = require('../lib/errors')
|
|
12
12
|
|
|
13
|
+
function getUrl (app) {
|
|
14
|
+
const { address, port } = app.server.address()
|
|
15
|
+
if (address === '::1') {
|
|
16
|
+
return `http://[${address}]:${port}`
|
|
17
|
+
} else {
|
|
18
|
+
return `http://${address}:${port}`
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
13
22
|
test('route', t => {
|
|
14
23
|
t.plan(9)
|
|
15
24
|
const test = t.test
|
|
@@ -203,7 +212,7 @@ test('same route definition object on multiple prefixes', async t => {
|
|
|
203
212
|
url: '/simple'
|
|
204
213
|
}
|
|
205
214
|
|
|
206
|
-
const fastify = Fastify()
|
|
215
|
+
const fastify = Fastify({ exposeHeadRoutes: false })
|
|
207
216
|
|
|
208
217
|
fastify.register(async function (f) {
|
|
209
218
|
f.addHook('onRoute', (routeOptions) => {
|
|
@@ -536,15 +545,15 @@ test('throws when route with empty url', async t => {
|
|
|
536
545
|
|
|
537
546
|
const fastify = Fastify()
|
|
538
547
|
try {
|
|
539
|
-
|
|
548
|
+
fastify.route({
|
|
540
549
|
method: 'GET',
|
|
541
550
|
url: '',
|
|
542
551
|
handler: (req, res) => {
|
|
543
552
|
res.send('hi!')
|
|
544
553
|
}
|
|
545
|
-
})
|
|
554
|
+
})
|
|
546
555
|
} catch (err) {
|
|
547
|
-
t.equal(err.message, 'The
|
|
556
|
+
t.equal(err.message, 'The path could not be empty')
|
|
548
557
|
}
|
|
549
558
|
})
|
|
550
559
|
|
|
@@ -553,10 +562,10 @@ test('throws when route with empty url in shorthand declaration', async t => {
|
|
|
553
562
|
|
|
554
563
|
const fastify = Fastify()
|
|
555
564
|
try {
|
|
556
|
-
|
|
565
|
+
fastify.get(
|
|
557
566
|
'',
|
|
558
567
|
async function handler () { return {} }
|
|
559
|
-
)
|
|
568
|
+
)
|
|
560
569
|
} catch (err) {
|
|
561
570
|
t.equal(err.message, 'The path could not be empty')
|
|
562
571
|
}
|
|
@@ -581,6 +590,86 @@ test('throws when route-level error handler is not a function', t => {
|
|
|
581
590
|
}
|
|
582
591
|
})
|
|
583
592
|
|
|
593
|
+
test('Creates a HEAD route for each GET one (default)', t => {
|
|
594
|
+
t.plan(8)
|
|
595
|
+
|
|
596
|
+
const fastify = Fastify()
|
|
597
|
+
|
|
598
|
+
fastify.route({
|
|
599
|
+
method: 'GET',
|
|
600
|
+
path: '/more-coffee',
|
|
601
|
+
handler: (req, reply) => {
|
|
602
|
+
reply.send({ here: 'is coffee' })
|
|
603
|
+
}
|
|
604
|
+
})
|
|
605
|
+
|
|
606
|
+
fastify.route({
|
|
607
|
+
method: 'GET',
|
|
608
|
+
path: '/some-light',
|
|
609
|
+
handler: (req, reply) => {
|
|
610
|
+
reply.send('Get some light!')
|
|
611
|
+
}
|
|
612
|
+
})
|
|
613
|
+
|
|
614
|
+
fastify.inject({
|
|
615
|
+
method: 'HEAD',
|
|
616
|
+
url: '/more-coffee'
|
|
617
|
+
}, (error, res) => {
|
|
618
|
+
t.error(error)
|
|
619
|
+
t.equal(res.statusCode, 200)
|
|
620
|
+
t.equal(res.headers['content-type'], 'application/json; charset=utf-8')
|
|
621
|
+
t.same(res.body, '')
|
|
622
|
+
})
|
|
623
|
+
|
|
624
|
+
fastify.inject({
|
|
625
|
+
method: 'HEAD',
|
|
626
|
+
url: '/some-light'
|
|
627
|
+
}, (error, res) => {
|
|
628
|
+
t.error(error)
|
|
629
|
+
t.equal(res.statusCode, 200)
|
|
630
|
+
t.equal(res.headers['content-type'], 'text/plain; charset=utf-8')
|
|
631
|
+
t.equal(res.body, '')
|
|
632
|
+
})
|
|
633
|
+
})
|
|
634
|
+
|
|
635
|
+
test('Do not create a HEAD route for each GET one (exposeHeadRoutes: false)', t => {
|
|
636
|
+
t.plan(4)
|
|
637
|
+
|
|
638
|
+
const fastify = Fastify({ exposeHeadRoutes: false })
|
|
639
|
+
|
|
640
|
+
fastify.route({
|
|
641
|
+
method: 'GET',
|
|
642
|
+
path: '/more-coffee',
|
|
643
|
+
handler: (req, reply) => {
|
|
644
|
+
reply.send({ here: 'is coffee' })
|
|
645
|
+
}
|
|
646
|
+
})
|
|
647
|
+
|
|
648
|
+
fastify.route({
|
|
649
|
+
method: 'GET',
|
|
650
|
+
path: '/some-light',
|
|
651
|
+
handler: (req, reply) => {
|
|
652
|
+
reply.send('Get some light!')
|
|
653
|
+
}
|
|
654
|
+
})
|
|
655
|
+
|
|
656
|
+
fastify.inject({
|
|
657
|
+
method: 'HEAD',
|
|
658
|
+
url: '/more-coffee'
|
|
659
|
+
}, (error, res) => {
|
|
660
|
+
t.error(error)
|
|
661
|
+
t.equal(res.statusCode, 404)
|
|
662
|
+
})
|
|
663
|
+
|
|
664
|
+
fastify.inject({
|
|
665
|
+
method: 'HEAD',
|
|
666
|
+
url: '/some-light'
|
|
667
|
+
}, (error, res) => {
|
|
668
|
+
t.error(error)
|
|
669
|
+
t.equal(res.statusCode, 404)
|
|
670
|
+
})
|
|
671
|
+
})
|
|
672
|
+
|
|
584
673
|
test('Creates a HEAD route for each GET one', t => {
|
|
585
674
|
t.plan(8)
|
|
586
675
|
|
|
@@ -811,7 +900,7 @@ test('HEAD route should handle properly each response type', t => {
|
|
|
811
900
|
}, (error, res) => {
|
|
812
901
|
t.error(error)
|
|
813
902
|
t.equal(res.statusCode, 200)
|
|
814
|
-
t.equal(res.headers['content-type'],
|
|
903
|
+
t.equal(res.headers['content-type'], undefined)
|
|
815
904
|
t.equal(res.headers['content-length'], undefined)
|
|
816
905
|
t.equal(res.body, '')
|
|
817
906
|
})
|
|
@@ -959,11 +1048,11 @@ test("HEAD route should handle stream.on('error')", t => {
|
|
|
959
1048
|
}, (error, res) => {
|
|
960
1049
|
t.error(error)
|
|
961
1050
|
t.equal(res.statusCode, 200)
|
|
962
|
-
t.equal(res.headers['content-type'],
|
|
1051
|
+
t.equal(res.headers['content-type'], undefined)
|
|
963
1052
|
})
|
|
964
1053
|
})
|
|
965
1054
|
|
|
966
|
-
test('HEAD route should
|
|
1055
|
+
test('HEAD route should be exposed by default', t => {
|
|
967
1056
|
t.plan(7)
|
|
968
1057
|
|
|
969
1058
|
const resStream = stream.Readable.from('Hello with error!')
|
|
@@ -992,7 +1081,7 @@ test('HEAD route should not be exposed by default', t => {
|
|
|
992
1081
|
url: '/without-flag'
|
|
993
1082
|
}, (error, res) => {
|
|
994
1083
|
t.error(error)
|
|
995
|
-
t.equal(res.statusCode,
|
|
1084
|
+
t.equal(res.statusCode, 200)
|
|
996
1085
|
})
|
|
997
1086
|
|
|
998
1087
|
fastify.inject({
|
|
@@ -1248,26 +1337,121 @@ test('Will not try to re-createprefixed HEAD route if it already exists and expo
|
|
|
1248
1337
|
t.ok(true)
|
|
1249
1338
|
})
|
|
1250
1339
|
|
|
1251
|
-
test('
|
|
1252
|
-
t.plan(
|
|
1340
|
+
test('GET route with body schema should throw', t => {
|
|
1341
|
+
t.plan(1)
|
|
1253
1342
|
|
|
1254
1343
|
const fastify = Fastify()
|
|
1255
1344
|
|
|
1256
1345
|
t.throws(() => {
|
|
1257
1346
|
fastify.route({
|
|
1258
1347
|
method: 'GET',
|
|
1259
|
-
path: '/
|
|
1348
|
+
path: '/get',
|
|
1349
|
+
schema: {
|
|
1350
|
+
body: {}
|
|
1351
|
+
},
|
|
1352
|
+
handler: function (req, reply) {
|
|
1353
|
+
reply.send({ hello: 'world' })
|
|
1354
|
+
}
|
|
1260
1355
|
})
|
|
1261
|
-
}, new Error('
|
|
1356
|
+
}, new Error('Body validation schema for GET:/get route is not supported!'))
|
|
1357
|
+
})
|
|
1358
|
+
|
|
1359
|
+
test('HEAD route with body schema should throw', t => {
|
|
1360
|
+
t.plan(1)
|
|
1361
|
+
|
|
1362
|
+
const fastify = Fastify()
|
|
1262
1363
|
|
|
1263
1364
|
t.throws(() => {
|
|
1264
1365
|
fastify.route({
|
|
1265
|
-
method: '
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1366
|
+
method: 'HEAD',
|
|
1367
|
+
path: '/shouldThrow',
|
|
1368
|
+
schema: {
|
|
1369
|
+
body: {}
|
|
1370
|
+
},
|
|
1371
|
+
handler: function (req, reply) {
|
|
1372
|
+
reply.send({ hello: 'world' })
|
|
1373
|
+
}
|
|
1374
|
+
})
|
|
1375
|
+
}, new Error('Body validation schema for HEAD:/shouldThrow route is not supported!'))
|
|
1376
|
+
})
|
|
1377
|
+
|
|
1378
|
+
test('[HEAD, GET] route with body schema should throw', t => {
|
|
1379
|
+
t.plan(1)
|
|
1380
|
+
|
|
1381
|
+
const fastify = Fastify()
|
|
1382
|
+
|
|
1383
|
+
t.throws(() => {
|
|
1384
|
+
fastify.route({
|
|
1385
|
+
method: ['HEAD', 'GET'],
|
|
1386
|
+
path: '/shouldThrowHead',
|
|
1387
|
+
schema: {
|
|
1388
|
+
body: {}
|
|
1389
|
+
},
|
|
1390
|
+
handler: function (req, reply) {
|
|
1391
|
+
reply.send({ hello: 'world' })
|
|
1392
|
+
}
|
|
1393
|
+
})
|
|
1394
|
+
}, new Error('Body validation schema for HEAD:/shouldThrowHead route is not supported!'))
|
|
1395
|
+
})
|
|
1396
|
+
|
|
1397
|
+
test('GET route with body schema should throw - shorthand', t => {
|
|
1398
|
+
t.plan(1)
|
|
1399
|
+
|
|
1400
|
+
const fastify = Fastify()
|
|
1401
|
+
|
|
1402
|
+
t.throws(() => {
|
|
1403
|
+
fastify.get('/shouldThrow', {
|
|
1404
|
+
schema: {
|
|
1405
|
+
body: {}
|
|
1406
|
+
}
|
|
1407
|
+
},
|
|
1408
|
+
function (req, reply) {
|
|
1409
|
+
reply.send({ hello: 'world' })
|
|
1410
|
+
}
|
|
1411
|
+
)
|
|
1412
|
+
}, new Error('Body validation schema for GET:/shouldThrow route is not supported!'))
|
|
1413
|
+
})
|
|
1414
|
+
|
|
1415
|
+
test('HEAD route with body schema should throw - shorthand', t => {
|
|
1416
|
+
t.plan(1)
|
|
1417
|
+
|
|
1418
|
+
const fastify = Fastify()
|
|
1419
|
+
|
|
1420
|
+
t.throws(() => {
|
|
1421
|
+
fastify.head('/shouldThrow2', {
|
|
1422
|
+
schema: {
|
|
1423
|
+
body: {}
|
|
1424
|
+
}
|
|
1425
|
+
},
|
|
1426
|
+
function (req, reply) {
|
|
1427
|
+
reply.send({ hello: 'world' })
|
|
1428
|
+
}
|
|
1429
|
+
)
|
|
1430
|
+
}, new Error('Body validation schema for HEAD:/shouldThrow2 route is not supported!'))
|
|
1431
|
+
})
|
|
1432
|
+
|
|
1433
|
+
test('route with non-english characters', t => {
|
|
1434
|
+
t.plan(4)
|
|
1435
|
+
|
|
1436
|
+
const fastify = Fastify()
|
|
1437
|
+
|
|
1438
|
+
fastify.get('/föö', (request, reply) => {
|
|
1439
|
+
reply.send('here /föö')
|
|
1440
|
+
})
|
|
1441
|
+
|
|
1442
|
+
fastify.listen(0, err => {
|
|
1443
|
+
t.error(err)
|
|
1444
|
+
fastify.server.unref()
|
|
1445
|
+
|
|
1446
|
+
sget({
|
|
1447
|
+
method: 'GET',
|
|
1448
|
+
url: getUrl(fastify) + encodeURI('/föö')
|
|
1449
|
+
}, (err, response, body) => {
|
|
1450
|
+
t.error(err)
|
|
1451
|
+
t.equal(response.statusCode, 200)
|
|
1452
|
+
t.equal(body.toString(), 'here /föö')
|
|
1269
1453
|
})
|
|
1270
|
-
}
|
|
1454
|
+
})
|
|
1271
1455
|
})
|
|
1272
1456
|
|
|
1273
1457
|
test('invalid url attribute - non string URL', t => {
|
|
@@ -133,7 +133,7 @@ test('Should honor frameworkErrors option', t => {
|
|
|
133
133
|
},
|
|
134
134
|
(err, res) => {
|
|
135
135
|
t.error(err)
|
|
136
|
-
t.equal(res.body, '\'
|
|
136
|
+
t.equal(res.body, '\'/test/%world\' is not a valid url component - FST_ERR_BAD_URL')
|
|
137
137
|
}
|
|
138
138
|
)
|
|
139
139
|
})
|
|
@@ -98,7 +98,13 @@ test('Example - get schema encapsulated', async t => {
|
|
|
98
98
|
|
|
99
99
|
test('Example - validation', t => {
|
|
100
100
|
t.plan(1)
|
|
101
|
-
const fastify = Fastify(
|
|
101
|
+
const fastify = Fastify({
|
|
102
|
+
ajv: {
|
|
103
|
+
customOptions: {
|
|
104
|
+
allowUnionTypes: true
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
})
|
|
102
108
|
const handler = () => { }
|
|
103
109
|
|
|
104
110
|
const bodyJsonSchema = {
|
|
@@ -224,7 +230,7 @@ test('Example Joi', t => {
|
|
|
224
230
|
const fastify = Fastify()
|
|
225
231
|
const handler = () => { }
|
|
226
232
|
|
|
227
|
-
const Joi = require('
|
|
233
|
+
const Joi = require('joi')
|
|
228
234
|
fastify.post('/the/url', {
|
|
229
235
|
schema: {
|
|
230
236
|
body: Joi.object().keys({
|
|
@@ -431,7 +437,7 @@ test('Example - schemas examples', t => {
|
|
|
431
437
|
}
|
|
432
438
|
}
|
|
433
439
|
|
|
434
|
-
fastify.
|
|
440
|
+
fastify.post('/', {
|
|
435
441
|
handler,
|
|
436
442
|
schema: {
|
|
437
443
|
body: refToId,
|
|
@@ -450,7 +456,7 @@ test('should return custom error messages with ajv-errors', t => {
|
|
|
450
456
|
|
|
451
457
|
const fastify = Fastify({
|
|
452
458
|
ajv: {
|
|
453
|
-
customOptions: { allErrors: true
|
|
459
|
+
customOptions: { allErrors: true },
|
|
454
460
|
plugins: [
|
|
455
461
|
require('ajv-errors')
|
|
456
462
|
]
|
|
@@ -545,7 +551,7 @@ test('should return localized error messages with ajv-i18n', t => {
|
|
|
545
551
|
}, (err, res) => {
|
|
546
552
|
t.error(err)
|
|
547
553
|
t.same(JSON.parse(res.payload), [{
|
|
548
|
-
|
|
554
|
+
instancePath: '',
|
|
549
555
|
keyword: 'required',
|
|
550
556
|
message: 'должно иметь обязательное поле work',
|
|
551
557
|
params: { missingProperty: 'work' },
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const { test } = require('tap')
|
|
4
4
|
const Fastify = require('..')
|
|
5
5
|
const fp = require('fastify-plugin')
|
|
6
|
+
const deepClone = require('rfdc')({ circles: true, proto: false })
|
|
6
7
|
const Ajv = require('ajv')
|
|
7
8
|
const { kSchemaController } = require('../lib/symbols.js')
|
|
8
9
|
|
|
@@ -287,7 +288,7 @@ test('First level $ref', t => {
|
|
|
287
288
|
|
|
288
289
|
test('Customize validator compiler in instance and route', t => {
|
|
289
290
|
t.plan(28)
|
|
290
|
-
const fastify = Fastify()
|
|
291
|
+
const fastify = Fastify({ exposeHeadRoutes: false })
|
|
291
292
|
|
|
292
293
|
fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {
|
|
293
294
|
t.equal(method, 'POST') // run 4 times
|
|
@@ -827,7 +828,7 @@ test('Validation context in validation result', t => {
|
|
|
827
828
|
t.equal(err.validationContext, 'body')
|
|
828
829
|
reply.send()
|
|
829
830
|
})
|
|
830
|
-
fastify.
|
|
831
|
+
fastify.post('/', {
|
|
831
832
|
handler: echoParams,
|
|
832
833
|
schema: {
|
|
833
834
|
body: {
|
|
@@ -840,7 +841,7 @@ test('Validation context in validation result', t => {
|
|
|
840
841
|
}
|
|
841
842
|
})
|
|
842
843
|
fastify.inject({
|
|
843
|
-
method: '
|
|
844
|
+
method: 'POST',
|
|
844
845
|
url: '/',
|
|
845
846
|
payload: {} // body lacks required field, will fail validation
|
|
846
847
|
}, (err, res) => {
|
|
@@ -881,7 +882,7 @@ test('The schema build should not modify the input', t => {
|
|
|
881
882
|
]
|
|
882
883
|
})
|
|
883
884
|
|
|
884
|
-
fastify.
|
|
885
|
+
fastify.post('/', {
|
|
885
886
|
schema: {
|
|
886
887
|
description: 'get',
|
|
887
888
|
body: { $ref: 'second#' },
|
|
@@ -918,7 +919,11 @@ test('Cross schema reference with encapsulation references', t => {
|
|
|
918
919
|
t.plan(1)
|
|
919
920
|
|
|
920
921
|
const fastify = Fastify()
|
|
921
|
-
fastify.addSchema({
|
|
922
|
+
fastify.addSchema({
|
|
923
|
+
$id: 'http://foo/item',
|
|
924
|
+
type: 'object',
|
|
925
|
+
properties: { foo: { type: 'string' } }
|
|
926
|
+
})
|
|
922
927
|
|
|
923
928
|
const refItem = { $ref: 'http://foo/item#' }
|
|
924
929
|
|
|
@@ -949,15 +954,15 @@ test('Cross schema reference with encapsulation references', t => {
|
|
|
949
954
|
}
|
|
950
955
|
}
|
|
951
956
|
|
|
952
|
-
instance.get('/get', { schema: { response: { 200: multipleRef } } }, () => { })
|
|
953
|
-
instance.get('/double-get', { schema: {
|
|
957
|
+
instance.get('/get', { schema: { response: { 200: deepClone(multipleRef) } } }, () => { })
|
|
958
|
+
instance.get('/double-get', { schema: { querystring: multipleRef, response: { 200: multipleRef } } }, () => { })
|
|
954
959
|
instance.post('/post', { schema: { body: multipleRef, response: { 200: multipleRef } } }, () => { })
|
|
955
960
|
instance.post('/double', { schema: { response: { 200: { $ref: 'encapsulation' } } } }, () => { })
|
|
956
961
|
done()
|
|
957
962
|
}, { prefix: '/foo' })
|
|
958
963
|
|
|
959
964
|
fastify.post('/post', { schema: { body: refItem, response: { 200: refItem } } }, () => { })
|
|
960
|
-
fastify.get('/get', { schema: {
|
|
965
|
+
fastify.get('/get', { schema: { params: refItem, response: { 200: refItem } } }, () => { })
|
|
961
966
|
|
|
962
967
|
fastify.ready(err => {
|
|
963
968
|
t.error(err)
|
|
@@ -1009,7 +1014,7 @@ test('onReady hook has the compilers ready', t => {
|
|
|
1009
1014
|
fastify.get(`/${Math.random()}`, {
|
|
1010
1015
|
handler: (req, reply) => reply.send(),
|
|
1011
1016
|
schema: {
|
|
1012
|
-
|
|
1017
|
+
headers: { type: 'object' },
|
|
1013
1018
|
response: { 200: { type: 'object' } }
|
|
1014
1019
|
}
|
|
1015
1020
|
})
|
|
@@ -1099,7 +1104,7 @@ test('Check how many AJV instances are built #2 - verify validatorPool', t => {
|
|
|
1099
1104
|
})
|
|
1100
1105
|
|
|
1101
1106
|
function addRandomRoute (server) {
|
|
1102
|
-
server.
|
|
1107
|
+
server.post(`/${Math.random()}`,
|
|
1103
1108
|
{ schema: { body: { type: 'object' } } },
|
|
1104
1109
|
(req, reply) => reply.send()
|
|
1105
1110
|
)
|
|
@@ -1370,7 +1375,7 @@ test('setSchemaController: Inherits correctly parent schemas with a customized v
|
|
|
1370
1375
|
})
|
|
1371
1376
|
const json = res.json()
|
|
1372
1377
|
|
|
1373
|
-
t.equal(json.message, 'querystring
|
|
1378
|
+
t.equal(json.message, 'querystring/msg must be array')
|
|
1374
1379
|
t.equal(json.statusCode, 400)
|
|
1375
1380
|
t.equal(res.statusCode, 400, 'Should not coearce the string into array')
|
|
1376
1381
|
})
|
|
@@ -1481,7 +1486,7 @@ test('setSchemaController: Inherits buildSerializer from parent if not present w
|
|
|
1481
1486
|
const json = res.json()
|
|
1482
1487
|
|
|
1483
1488
|
t.equal(json.statusCode, 400)
|
|
1484
|
-
t.equal(json.message, 'querystring
|
|
1489
|
+
t.equal(json.message, 'querystring/msg must be array')
|
|
1485
1490
|
t.equal(rootSerializerCalled, 1, 'Should be called from the child')
|
|
1486
1491
|
t.equal(rootValidatorCalled, 0, 'Should not be called from the child')
|
|
1487
1492
|
t.equal(childValidatorCalled, 1, 'Should be called from the child')
|
|
@@ -1598,7 +1603,7 @@ test('setSchemaController: Inherits buildValidator from parent if not present wi
|
|
|
1598
1603
|
const json = res.json()
|
|
1599
1604
|
|
|
1600
1605
|
t.equal(json.statusCode, 400)
|
|
1601
|
-
t.equal(json.message, 'querystring
|
|
1606
|
+
t.equal(json.message, 'querystring/msg must be array')
|
|
1602
1607
|
t.equal(rootSerializerCalled, 0, 'Should be called from the child')
|
|
1603
1608
|
t.equal(rootValidatorCalled, 1, 'Should not be called from the child')
|
|
1604
1609
|
t.equal(childSerializerCalled, 1, 'Should be called from the child')
|
|
@@ -1683,14 +1688,14 @@ test('Should throw if not default validator passed', async t => {
|
|
|
1683
1688
|
}
|
|
1684
1689
|
})
|
|
1685
1690
|
|
|
1686
|
-
t.equal(res.json().message, 'querystring
|
|
1691
|
+
t.equal(res.json().message, 'querystring/msg must be array')
|
|
1687
1692
|
t.equal(res.statusCode, 400, 'Should not coearce the string into array')
|
|
1688
1693
|
} catch (err) {
|
|
1689
1694
|
t.error(err)
|
|
1690
1695
|
}
|
|
1691
1696
|
})
|
|
1692
1697
|
|
|
1693
|
-
test('Should
|
|
1698
|
+
test('Should coerce the array if the default validator is used', async t => {
|
|
1694
1699
|
t.plan(2)
|
|
1695
1700
|
const someSchema = {
|
|
1696
1701
|
$id: 'some',
|
|
@@ -1728,7 +1733,7 @@ test('Should throw if not default validator passed', async t => {
|
|
|
1728
1733
|
}
|
|
1729
1734
|
},
|
|
1730
1735
|
(req, reply) => {
|
|
1731
|
-
reply.send(
|
|
1736
|
+
reply.send(req.query)
|
|
1732
1737
|
}
|
|
1733
1738
|
)
|
|
1734
1739
|
|
|
@@ -1740,12 +1745,12 @@ test('Should throw if not default validator passed', async t => {
|
|
|
1740
1745
|
method: 'POST',
|
|
1741
1746
|
url: '/',
|
|
1742
1747
|
query: {
|
|
1743
|
-
msg:
|
|
1748
|
+
msg: 'string'
|
|
1744
1749
|
}
|
|
1745
1750
|
})
|
|
1746
1751
|
|
|
1747
|
-
t.equal(res.
|
|
1748
|
-
t.
|
|
1752
|
+
t.equal(res.statusCode, 200)
|
|
1753
|
+
t.same(res.json(), { msg: ['string'] }, 'Should coearce the string into array')
|
|
1749
1754
|
} catch (err) {
|
|
1750
1755
|
t.error(err)
|
|
1751
1756
|
}
|
|
@@ -163,7 +163,7 @@ test('Use shared schema and $ref with $id in response ($ref to $id)', t => {
|
|
|
163
163
|
t.equal(res.statusCode, 400)
|
|
164
164
|
t.same(res.json(), {
|
|
165
165
|
error: 'Bad Request',
|
|
166
|
-
message: "body
|
|
166
|
+
message: "body must have required property 'address'",
|
|
167
167
|
statusCode: 400
|
|
168
168
|
})
|
|
169
169
|
})
|
|
@@ -236,8 +236,7 @@ test('Shared schema should be pass to serializer and validator ($ref to shared s
|
|
|
236
236
|
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
237
237
|
title: 'List of Asset locations',
|
|
238
238
|
type: 'array',
|
|
239
|
-
items: { $ref: 'http://example.com/asset.json#' }
|
|
240
|
-
default: []
|
|
239
|
+
items: { $ref: 'http://example.com/asset.json#' }
|
|
241
240
|
}
|
|
242
241
|
|
|
243
242
|
fastify.post('/', {
|
|
@@ -273,7 +272,7 @@ test('Shared schema should be pass to serializer and validator ($ref to shared s
|
|
|
273
272
|
t.equal(res.statusCode, 400)
|
|
274
273
|
t.same(res.json(), {
|
|
275
274
|
error: 'Bad Request',
|
|
276
|
-
message: 'body
|
|
275
|
+
message: 'body/0/location/email must match format "email"',
|
|
277
276
|
statusCode: 400
|
|
278
277
|
})
|
|
279
278
|
})
|
|
@@ -282,7 +281,7 @@ test('Shared schema should be pass to serializer and validator ($ref to shared s
|
|
|
282
281
|
|
|
283
282
|
test('Custom setSerializerCompiler', t => {
|
|
284
283
|
t.plan(7)
|
|
285
|
-
const fastify = Fastify()
|
|
284
|
+
const fastify = Fastify({ exposeHeadRoutes: false })
|
|
286
285
|
|
|
287
286
|
const outSchema = {
|
|
288
287
|
$id: 'test',
|
|
@@ -355,7 +354,6 @@ test('Custom setSerializerCompiler returns bad serialized output', t => {
|
|
|
355
354
|
t.error(err)
|
|
356
355
|
t.equal(res.statusCode, 500)
|
|
357
356
|
t.strictSame(res.json(), {
|
|
358
|
-
error: 'Internal Server Error',
|
|
359
357
|
code: 'FST_ERR_REP_INVALID_PAYLOAD_TYPE',
|
|
360
358
|
message: 'Attempted to send payload of invalid type \'object\'. Expected a string or Buffer.',
|
|
361
359
|
statusCode: 500
|
|
@@ -410,11 +408,11 @@ test('Custom serializer per route', async t => {
|
|
|
410
408
|
res = await fastify.inject('/route')
|
|
411
409
|
t.equal(res.json().mean, 'route')
|
|
412
410
|
|
|
413
|
-
t.equal(hit,
|
|
411
|
+
t.equal(hit, 4, 'the custom and route serializer has been called')
|
|
414
412
|
})
|
|
415
413
|
|
|
416
414
|
test('Reply serializer win over serializer ', t => {
|
|
417
|
-
t.plan(
|
|
415
|
+
t.plan(6)
|
|
418
416
|
|
|
419
417
|
const fastify = Fastify()
|
|
420
418
|
fastify.setReplySerializer(function (payload, statusCode) {
|
|
@@ -453,7 +451,7 @@ test('Reply serializer win over serializer ', t => {
|
|
|
453
451
|
})
|
|
454
452
|
|
|
455
453
|
test('Reply serializer win over serializer ', t => {
|
|
456
|
-
t.plan(
|
|
454
|
+
t.plan(6)
|
|
457
455
|
|
|
458
456
|
const fastify = Fastify()
|
|
459
457
|
fastify.setReplySerializer(function (payload, statusCode) {
|
|
@@ -570,11 +568,13 @@ test('do not crash if status code serializer errors', async t => {
|
|
|
570
568
|
const fastify = Fastify()
|
|
571
569
|
|
|
572
570
|
const requiresFoo = {
|
|
571
|
+
type: 'object',
|
|
573
572
|
properties: { foo: { type: 'string' } },
|
|
574
573
|
required: ['foo']
|
|
575
574
|
}
|
|
576
575
|
|
|
577
576
|
const someUserErrorType2 = {
|
|
577
|
+
type: 'object',
|
|
578
578
|
properties: {
|
|
579
579
|
code: { type: 'number' }
|
|
580
580
|
},
|