fastify 4.5.3 → 4.7.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.
- package/docs/Guides/Ecosystem.md +42 -16
- package/docs/Guides/Migration-Guide-V4.md +97 -48
- package/docs/Guides/Plugins-Guide.md +44 -0
- package/docs/Guides/Write-Plugin.md +1 -1
- package/docs/Reference/Logging.md +16 -13
- package/docs/Reference/Reply.md +5 -5
- package/docs/Reference/Request.md +19 -6
- package/docs/Reference/Routes.md +2 -2
- package/docs/Reference/Server.md +24 -2
- package/docs/Reference/Type-Providers.md +5 -19
- package/docs/Reference/TypeScript.md +7 -14
- package/examples/typescript-server.ts +1 -1
- package/fastify.d.ts +2 -2
- package/fastify.js +4 -1
- package/lib/contentTypeParser.js +10 -9
- package/lib/context.js +27 -3
- package/lib/error-handler.js +7 -3
- package/lib/error-serializer.js +13 -40
- package/lib/handleRequest.js +15 -13
- package/lib/reply.js +42 -34
- package/lib/request.js +36 -18
- package/lib/route.js +25 -10
- package/lib/schema-controller.js +7 -1
- package/lib/schemas.js +1 -0
- package/lib/server.js +6 -1
- package/lib/symbols.js +2 -0
- package/lib/validation.js +4 -3
- package/lib/warnings.js +2 -0
- package/package.json +26 -26
- package/test/404s.test.js +19 -1
- package/test/context-config.test.js +2 -1
- package/test/handler-context.test.js +12 -30
- package/test/has-route.test.js +77 -0
- package/test/internals/contentTypeParser.test.js +3 -3
- package/test/internals/handleRequest.test.js +4 -3
- package/test/internals/reply-serialize.test.js +9 -9
- package/test/internals/reply.test.js +10 -9
- package/test/internals/request-validate.test.js +97 -9
- package/test/internals/request.test.js +57 -3
- package/test/internals/validation.test.js +15 -0
- package/test/listen.deprecated.test.js +33 -0
- package/test/plugin.test.js +1 -1
- package/test/reply-code.test.js +59 -0
- package/test/route.test.js +29 -0
- package/test/router-options.test.js +33 -66
- package/test/schema-feature.test.js +25 -0
- package/test/schema-special-usage.test.js +29 -0
- package/test/schema-validation.test.js +19 -0
- package/test/search.test.js +169 -30
- package/test/server.test.js +54 -0
- package/test/types/fastify.test-d.ts +9 -0
- package/test/types/route.test-d.ts +11 -0
- package/test/unsupported-httpversion.test.js +0 -26
- package/types/hooks.d.ts +25 -25
- package/types/instance.d.ts +27 -21
- package/types/logger.d.ts +1 -1
- package/types/plugin.d.ts +3 -3
- package/types/reply.d.ts +2 -2
- package/types/request.d.ts +11 -5
- package/types/route.d.ts +9 -9
|
@@ -268,6 +268,21 @@ test('build schema - headers are not lowercased in case of custom object', t =>
|
|
|
268
268
|
})
|
|
269
269
|
})
|
|
270
270
|
|
|
271
|
+
test('build schema - headers are not lowercased in case of custom validator provided', t => {
|
|
272
|
+
t.plan(1)
|
|
273
|
+
|
|
274
|
+
class Headers {}
|
|
275
|
+
const opts = {
|
|
276
|
+
schema: {
|
|
277
|
+
headers: new Headers()
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => {
|
|
281
|
+
t.type(schema, Headers)
|
|
282
|
+
return () => {}
|
|
283
|
+
}, true)
|
|
284
|
+
})
|
|
285
|
+
|
|
271
286
|
test('build schema - uppercased headers are not included', t => {
|
|
272
287
|
t.plan(1)
|
|
273
288
|
const opts = {
|
|
@@ -200,3 +200,36 @@ test('listen when firstArg is { path: string(pipe) } and with backlog and callba
|
|
|
200
200
|
t.equal(address, '\\\\.\\pipe\\testPipe3')
|
|
201
201
|
})
|
|
202
202
|
})
|
|
203
|
+
|
|
204
|
+
test('listen accepts a port as string, and callback', t => {
|
|
205
|
+
t.plan(2)
|
|
206
|
+
const fastify = Fastify()
|
|
207
|
+
t.teardown(fastify.close.bind(fastify))
|
|
208
|
+
const port = 3000
|
|
209
|
+
fastify.listen(port.toString(), localhost, (err) => {
|
|
210
|
+
t.equal(fastify.server.address().port, port)
|
|
211
|
+
t.error(err)
|
|
212
|
+
})
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
test('listen accepts a port as string, address and callback', t => {
|
|
216
|
+
t.plan(3)
|
|
217
|
+
const fastify = Fastify()
|
|
218
|
+
t.teardown(fastify.close.bind(fastify))
|
|
219
|
+
const port = 3000
|
|
220
|
+
fastify.listen(port.toString(), localhost, (err) => {
|
|
221
|
+
t.equal(fastify.server.address().port, port)
|
|
222
|
+
t.equal(fastify.server.address().address, localhost)
|
|
223
|
+
t.error(err)
|
|
224
|
+
})
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
test('listen with invalid port string without callback with (address)', t => {
|
|
228
|
+
t.plan(1)
|
|
229
|
+
const fastify = Fastify()
|
|
230
|
+
t.teardown(fastify.close.bind(fastify))
|
|
231
|
+
fastify.listen('-1')
|
|
232
|
+
.then(address => {
|
|
233
|
+
t.equal(address, `http://${localhostForURL}:${fastify.server.address().port}`)
|
|
234
|
+
})
|
|
235
|
+
})
|
package/test/plugin.test.js
CHANGED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const Fastify = require('..')
|
|
6
|
+
|
|
7
|
+
test('code should handle null/undefined/float', t => {
|
|
8
|
+
t.plan(8)
|
|
9
|
+
|
|
10
|
+
const fastify = Fastify()
|
|
11
|
+
|
|
12
|
+
fastify.get('/null', function (request, reply) {
|
|
13
|
+
reply.status(null).send()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
fastify.get('/undefined', function (request, reply) {
|
|
17
|
+
reply.status(undefined).send()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
fastify.get('/404.5', function (request, reply) {
|
|
21
|
+
reply.status(404.5).send()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
fastify.inject({
|
|
25
|
+
method: 'GET',
|
|
26
|
+
url: '/null'
|
|
27
|
+
}, (error, res) => {
|
|
28
|
+
t.error(error)
|
|
29
|
+
t.equal(res.statusCode, 500)
|
|
30
|
+
t.same(res.json(), {
|
|
31
|
+
statusCode: 500,
|
|
32
|
+
code: 'FST_ERR_BAD_STATUS_CODE',
|
|
33
|
+
error: 'Internal Server Error',
|
|
34
|
+
message: 'Called reply with an invalid status code: null'
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
fastify.inject({
|
|
39
|
+
method: 'GET',
|
|
40
|
+
url: '/undefined'
|
|
41
|
+
}, (error, res) => {
|
|
42
|
+
t.error(error)
|
|
43
|
+
t.equal(res.statusCode, 500)
|
|
44
|
+
t.same(res.json(), {
|
|
45
|
+
statusCode: 500,
|
|
46
|
+
code: 'FST_ERR_BAD_STATUS_CODE',
|
|
47
|
+
error: 'Internal Server Error',
|
|
48
|
+
message: 'Called reply with an invalid status code: undefined'
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
fastify.inject({
|
|
53
|
+
method: 'GET',
|
|
54
|
+
url: '/404.5'
|
|
55
|
+
}, (error, res) => {
|
|
56
|
+
t.error(error)
|
|
57
|
+
t.equal(res.statusCode, 404)
|
|
58
|
+
})
|
|
59
|
+
})
|
package/test/route.test.js
CHANGED
|
@@ -1464,3 +1464,32 @@ test('invalid url attribute - non string URL', t => {
|
|
|
1464
1464
|
t.equal(error.code, FST_ERR_INVALID_URL().code)
|
|
1465
1465
|
}
|
|
1466
1466
|
})
|
|
1467
|
+
|
|
1468
|
+
test('exposeHeadRoute should not reuse the same route option', async t => {
|
|
1469
|
+
t.plan(2)
|
|
1470
|
+
|
|
1471
|
+
const fastify = Fastify()
|
|
1472
|
+
|
|
1473
|
+
// we update the onRequest hook in onRoute hook
|
|
1474
|
+
// if we reuse the same route option
|
|
1475
|
+
// that means we will append another function inside the array
|
|
1476
|
+
fastify.addHook('onRoute', function (routeOption) {
|
|
1477
|
+
if (Array.isArray(routeOption.onRequest)) {
|
|
1478
|
+
routeOption.onRequest.push(() => {})
|
|
1479
|
+
} else {
|
|
1480
|
+
routeOption.onRequest = [() => {}]
|
|
1481
|
+
}
|
|
1482
|
+
})
|
|
1483
|
+
|
|
1484
|
+
fastify.addHook('onRoute', function (routeOption) {
|
|
1485
|
+
t.equal(routeOption.onRequest.length, 1)
|
|
1486
|
+
})
|
|
1487
|
+
|
|
1488
|
+
fastify.route({
|
|
1489
|
+
method: 'GET',
|
|
1490
|
+
path: '/more-coffee',
|
|
1491
|
+
async handler () {
|
|
1492
|
+
return 'hello world'
|
|
1493
|
+
}
|
|
1494
|
+
})
|
|
1495
|
+
})
|
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const test = require('tap').test
|
|
4
|
-
const sget = require('simple-get')
|
|
5
4
|
const Fastify = require('../')
|
|
6
5
|
const { FST_ERR_BAD_URL } = require('../lib/errors')
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
const { address, port } = app.server.address()
|
|
10
|
-
if (address === '::1') {
|
|
11
|
-
return `http://[${address}]:${port}`
|
|
12
|
-
} else {
|
|
13
|
-
return `http://${address}:${port}`
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
test('Should honor ignoreTrailingSlash option', t => {
|
|
7
|
+
test('Should honor ignoreTrailingSlash option', async t => {
|
|
18
8
|
t.plan(4)
|
|
19
9
|
const fastify = Fastify({
|
|
20
10
|
ignoreTrailingSlash: true
|
|
@@ -24,27 +14,16 @@ test('Should honor ignoreTrailingSlash option', t => {
|
|
|
24
14
|
res.send('test')
|
|
25
15
|
})
|
|
26
16
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const baseUrl = getUrl(fastify)
|
|
32
|
-
|
|
33
|
-
sget.concat(baseUrl + '/test', (err, res, data) => {
|
|
34
|
-
if (err) t.threw(err)
|
|
35
|
-
t.equal(res.statusCode, 200)
|
|
36
|
-
t.equal(data.toString(), 'test')
|
|
37
|
-
})
|
|
17
|
+
let res = await fastify.inject('/test')
|
|
18
|
+
t.equal(res.statusCode, 200)
|
|
19
|
+
t.equal(res.payload.toString(), 'test')
|
|
38
20
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
t.equal(data.toString(), 'test')
|
|
43
|
-
})
|
|
44
|
-
})
|
|
21
|
+
res = await fastify.inject('/test/')
|
|
22
|
+
t.equal(res.statusCode, 200)
|
|
23
|
+
t.equal(res.payload.toString(), 'test')
|
|
45
24
|
})
|
|
46
25
|
|
|
47
|
-
test('Should honor ignoreDuplicateSlashes option', t => {
|
|
26
|
+
test('Should honor ignoreDuplicateSlashes option', async t => {
|
|
48
27
|
t.plan(4)
|
|
49
28
|
const fastify = Fastify({
|
|
50
29
|
ignoreDuplicateSlashes: true
|
|
@@ -54,27 +33,16 @@ test('Should honor ignoreDuplicateSlashes option', t => {
|
|
|
54
33
|
res.send('test')
|
|
55
34
|
})
|
|
56
35
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const baseUrl = getUrl(fastify)
|
|
62
|
-
|
|
63
|
-
sget.concat(baseUrl + '/test/test/test', (err, res, data) => {
|
|
64
|
-
if (err) t.threw(err)
|
|
65
|
-
t.equal(res.statusCode, 200)
|
|
66
|
-
t.equal(data.toString(), 'test')
|
|
67
|
-
})
|
|
36
|
+
let res = await fastify.inject('/test/test/test')
|
|
37
|
+
t.equal(res.statusCode, 200)
|
|
38
|
+
t.equal(res.payload.toString(), 'test')
|
|
68
39
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
t.equal(data.toString(), 'test')
|
|
73
|
-
})
|
|
74
|
-
})
|
|
40
|
+
res = await fastify.inject('/test//test///test')
|
|
41
|
+
t.equal(res.statusCode, 200)
|
|
42
|
+
t.equal(res.payload.toString(), 'test')
|
|
75
43
|
})
|
|
76
44
|
|
|
77
|
-
test('Should honor ignoreTrailingSlash and ignoreDuplicateSlashes options', t => {
|
|
45
|
+
test('Should honor ignoreTrailingSlash and ignoreDuplicateSlashes options', async t => {
|
|
78
46
|
t.plan(4)
|
|
79
47
|
const fastify = Fastify({
|
|
80
48
|
ignoreTrailingSlash: true,
|
|
@@ -85,24 +53,13 @@ test('Should honor ignoreTrailingSlash and ignoreDuplicateSlashes options', t =>
|
|
|
85
53
|
res.send('test')
|
|
86
54
|
})
|
|
87
55
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const baseUrl = getUrl(fastify)
|
|
56
|
+
let res = await fastify.inject('/test/test/test/')
|
|
57
|
+
t.equal(res.statusCode, 200)
|
|
58
|
+
t.equal(res.payload.toString(), 'test')
|
|
93
59
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
t.equal(data.toString(), 'test')
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
sget.concat(baseUrl + '/test//test///test//', (err, res, data) => {
|
|
101
|
-
if (err) t.threw(err)
|
|
102
|
-
t.equal(res.statusCode, 200)
|
|
103
|
-
t.equal(data.toString(), 'test')
|
|
104
|
-
})
|
|
105
|
-
})
|
|
60
|
+
res = await fastify.inject('/test//test///test//')
|
|
61
|
+
t.equal(res.statusCode, 200)
|
|
62
|
+
t.equal(res.payload.toString(), 'test')
|
|
106
63
|
})
|
|
107
64
|
|
|
108
65
|
test('Should honor maxParamLength option', t => {
|
|
@@ -131,12 +88,22 @@ test('Should honor maxParamLength option', t => {
|
|
|
131
88
|
})
|
|
132
89
|
|
|
133
90
|
test('Should expose router options via getters on request and reply', t => {
|
|
134
|
-
t.plan(
|
|
91
|
+
t.plan(10)
|
|
135
92
|
const fastify = Fastify()
|
|
93
|
+
const expectedSchema = {
|
|
94
|
+
params: {
|
|
95
|
+
id: { type: 'integer' }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
136
98
|
|
|
137
|
-
fastify.get('/test/:id',
|
|
99
|
+
fastify.get('/test/:id', {
|
|
100
|
+
schema: expectedSchema
|
|
101
|
+
}, (req, reply) => {
|
|
138
102
|
t.equal(reply.context.config.url, '/test/:id')
|
|
139
103
|
t.equal(reply.context.config.method, 'GET')
|
|
104
|
+
t.equal(req.routeConfig.url, '/test/:id')
|
|
105
|
+
t.equal(req.routeConfig.method, 'GET')
|
|
106
|
+
t.same(req.routeSchema, expectedSchema)
|
|
140
107
|
t.equal(req.routerPath, '/test/:id')
|
|
141
108
|
t.equal(req.routerMethod, 'GET')
|
|
142
109
|
t.equal(req.is404, false)
|
|
@@ -1779,3 +1779,28 @@ test('Should return a human-friendly error if response status codes are not spec
|
|
|
1779
1779
|
t.match(err.message, 'Failed building the serialization schema for GET: /, due to error response schemas should be nested under a valid status code, e.g { 2xx: { type: "object" } }')
|
|
1780
1780
|
})
|
|
1781
1781
|
})
|
|
1782
|
+
|
|
1783
|
+
test('setSchemaController: custom validator instance should not mutate headers schema', async t => {
|
|
1784
|
+
t.plan(2)
|
|
1785
|
+
class Headers {}
|
|
1786
|
+
const fastify = Fastify()
|
|
1787
|
+
|
|
1788
|
+
fastify.setSchemaController({
|
|
1789
|
+
compilersFactory: {
|
|
1790
|
+
buildValidator: function () {
|
|
1791
|
+
return ({ schema, method, url, httpPart }) => {
|
|
1792
|
+
t.type(schema, Headers)
|
|
1793
|
+
return () => {}
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
})
|
|
1798
|
+
|
|
1799
|
+
fastify.get('/', {
|
|
1800
|
+
schema: {
|
|
1801
|
+
headers: new Headers()
|
|
1802
|
+
}
|
|
1803
|
+
}, () => {})
|
|
1804
|
+
|
|
1805
|
+
await fastify.ready()
|
|
1806
|
+
})
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { test } = require('tap')
|
|
4
4
|
const Joi = require('joi')
|
|
5
|
+
const yup = require('yup')
|
|
5
6
|
const AJV = require('ajv')
|
|
6
7
|
const S = require('fluent-json-schema')
|
|
7
8
|
const Fastify = require('..')
|
|
@@ -673,3 +674,31 @@ test('JOI validation overwrite request headers', t => {
|
|
|
673
674
|
})
|
|
674
675
|
})
|
|
675
676
|
})
|
|
677
|
+
|
|
678
|
+
test('Custom schema object should not trigger FST_ERR_SCH_DUPLICATE', async t => {
|
|
679
|
+
const fastify = Fastify()
|
|
680
|
+
const handler = () => { }
|
|
681
|
+
|
|
682
|
+
fastify.get('/the/url', {
|
|
683
|
+
schema: {
|
|
684
|
+
query: yup.object({
|
|
685
|
+
foo: yup.string()
|
|
686
|
+
})
|
|
687
|
+
},
|
|
688
|
+
validatorCompiler: ({ schema, method, url, httpPart }) => {
|
|
689
|
+
return function (data) {
|
|
690
|
+
// with option strict = false, yup `validateSync` function returns the coerced value if validation was successful, or throws if validation failed
|
|
691
|
+
try {
|
|
692
|
+
const result = schema.validateSync(data, {})
|
|
693
|
+
return { value: result }
|
|
694
|
+
} catch (e) {
|
|
695
|
+
return { error: e }
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
},
|
|
699
|
+
handler
|
|
700
|
+
})
|
|
701
|
+
|
|
702
|
+
await fastify.ready()
|
|
703
|
+
t.pass('fastify is ready')
|
|
704
|
+
})
|
|
@@ -1017,3 +1017,22 @@ test("The same $id in route's schema must not overwrite others", t => {
|
|
|
1017
1017
|
t.same(res.payload, 'ok')
|
|
1018
1018
|
})
|
|
1019
1019
|
})
|
|
1020
|
+
|
|
1021
|
+
test('Custom validator compiler should not mutate schema', async t => {
|
|
1022
|
+
t.plan(2)
|
|
1023
|
+
class Headers {}
|
|
1024
|
+
const fastify = Fastify()
|
|
1025
|
+
|
|
1026
|
+
fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {
|
|
1027
|
+
t.type(schema, Headers)
|
|
1028
|
+
return () => {}
|
|
1029
|
+
})
|
|
1030
|
+
|
|
1031
|
+
fastify.get('/', {
|
|
1032
|
+
schema: {
|
|
1033
|
+
headers: new Headers()
|
|
1034
|
+
}
|
|
1035
|
+
}, () => {})
|
|
1036
|
+
|
|
1037
|
+
await fastify.ready()
|
|
1038
|
+
})
|
package/test/search.test.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const t = require('tap')
|
|
4
|
+
const sget = require('simple-get').concat
|
|
4
5
|
const test = t.test
|
|
5
6
|
const fastify = require('..')()
|
|
6
7
|
|
|
7
8
|
const schema = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
'
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
type: 'string'
|
|
15
|
-
}
|
|
9
|
+
response: {
|
|
10
|
+
'2xx': {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
hello: {
|
|
14
|
+
type: 'string'
|
|
16
15
|
}
|
|
17
16
|
}
|
|
18
17
|
}
|
|
@@ -20,35 +19,45 @@ const schema = {
|
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
const querySchema = {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
type: 'integer'
|
|
29
|
-
}
|
|
22
|
+
querystring: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
hello: {
|
|
26
|
+
type: 'integer'
|
|
30
27
|
}
|
|
31
28
|
}
|
|
32
29
|
}
|
|
33
30
|
}
|
|
34
31
|
|
|
35
32
|
const paramsSchema = {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
type: 'integer'
|
|
45
|
-
}
|
|
33
|
+
params: {
|
|
34
|
+
type: 'object',
|
|
35
|
+
properties: {
|
|
36
|
+
foo: {
|
|
37
|
+
type: 'string'
|
|
38
|
+
},
|
|
39
|
+
test: {
|
|
40
|
+
type: 'integer'
|
|
46
41
|
}
|
|
47
42
|
}
|
|
48
43
|
}
|
|
49
44
|
}
|
|
50
45
|
|
|
51
|
-
|
|
46
|
+
const bodySchema = {
|
|
47
|
+
body: {
|
|
48
|
+
type: 'object',
|
|
49
|
+
properties: {
|
|
50
|
+
foo: {
|
|
51
|
+
type: 'string'
|
|
52
|
+
},
|
|
53
|
+
test: {
|
|
54
|
+
type: 'integer'
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
test('search', t => {
|
|
52
61
|
t.plan(1)
|
|
53
62
|
try {
|
|
54
63
|
fastify.route({
|
|
@@ -65,13 +74,13 @@ test('shorthand - search', t => {
|
|
|
65
74
|
}
|
|
66
75
|
})
|
|
67
76
|
|
|
68
|
-
test('
|
|
77
|
+
test('search, params schema', t => {
|
|
69
78
|
t.plan(1)
|
|
70
79
|
try {
|
|
71
80
|
fastify.route({
|
|
72
81
|
method: 'SEARCH',
|
|
73
82
|
url: '/params/:foo/:test',
|
|
74
|
-
paramsSchema,
|
|
83
|
+
schema: paramsSchema,
|
|
75
84
|
handler: function (request, reply) {
|
|
76
85
|
reply.code(200).send(request.params)
|
|
77
86
|
}
|
|
@@ -82,13 +91,13 @@ test('shorthand - search params', t => {
|
|
|
82
91
|
}
|
|
83
92
|
})
|
|
84
93
|
|
|
85
|
-
test('
|
|
94
|
+
test('search, querystring schema', t => {
|
|
86
95
|
t.plan(1)
|
|
87
96
|
try {
|
|
88
97
|
fastify.route({
|
|
89
98
|
method: 'SEARCH',
|
|
90
99
|
url: '/query',
|
|
91
|
-
querySchema,
|
|
100
|
+
schema: querySchema,
|
|
92
101
|
handler: function (request, reply) {
|
|
93
102
|
reply.code(200).send(request.query)
|
|
94
103
|
}
|
|
@@ -98,3 +107,133 @@ test('shorthand - get, querystring schema', t => {
|
|
|
98
107
|
t.fail()
|
|
99
108
|
}
|
|
100
109
|
})
|
|
110
|
+
|
|
111
|
+
test('search, body schema', t => {
|
|
112
|
+
t.plan(1)
|
|
113
|
+
try {
|
|
114
|
+
fastify.route({
|
|
115
|
+
method: 'SEARCH',
|
|
116
|
+
url: '/body',
|
|
117
|
+
schema: bodySchema,
|
|
118
|
+
handler: function (request, reply) {
|
|
119
|
+
reply.code(200).send(request.body)
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
t.pass()
|
|
123
|
+
} catch (e) {
|
|
124
|
+
t.fail()
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
fastify.listen({ port: 0 }, err => {
|
|
129
|
+
t.error(err)
|
|
130
|
+
t.teardown(() => { fastify.close() })
|
|
131
|
+
|
|
132
|
+
const url = `http://localhost:${fastify.server.address().port}`
|
|
133
|
+
|
|
134
|
+
test('request - search', t => {
|
|
135
|
+
t.plan(4)
|
|
136
|
+
sget({
|
|
137
|
+
method: 'SEARCH',
|
|
138
|
+
url
|
|
139
|
+
}, (err, response, body) => {
|
|
140
|
+
t.error(err)
|
|
141
|
+
t.equal(response.statusCode, 200)
|
|
142
|
+
t.equal(response.headers['content-length'], '' + body.length)
|
|
143
|
+
t.same(JSON.parse(body), { hello: 'world' })
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
test('request search params schema', t => {
|
|
148
|
+
t.plan(4)
|
|
149
|
+
sget({
|
|
150
|
+
method: 'SEARCH',
|
|
151
|
+
url: `${url}/params/world/123`
|
|
152
|
+
}, (err, response, body) => {
|
|
153
|
+
t.error(err)
|
|
154
|
+
t.equal(response.statusCode, 200)
|
|
155
|
+
t.equal(response.headers['content-length'], '' + body.length)
|
|
156
|
+
t.same(JSON.parse(body), { foo: 'world', test: 123 })
|
|
157
|
+
})
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
test('request search params schema error', t => {
|
|
161
|
+
t.plan(3)
|
|
162
|
+
sget({
|
|
163
|
+
method: 'SEARCH',
|
|
164
|
+
url: `${url}/params/world/string`
|
|
165
|
+
}, (err, response, body) => {
|
|
166
|
+
t.error(err)
|
|
167
|
+
t.equal(response.statusCode, 400)
|
|
168
|
+
t.same(JSON.parse(body), {
|
|
169
|
+
error: 'Bad Request',
|
|
170
|
+
message: 'params/test must be integer',
|
|
171
|
+
statusCode: 400
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
test('request search querystring schema', t => {
|
|
177
|
+
t.plan(4)
|
|
178
|
+
sget({
|
|
179
|
+
method: 'SEARCH',
|
|
180
|
+
url: `${url}/query?hello=123`
|
|
181
|
+
}, (err, response, body) => {
|
|
182
|
+
t.error(err)
|
|
183
|
+
t.equal(response.statusCode, 200)
|
|
184
|
+
t.equal(response.headers['content-length'], '' + body.length)
|
|
185
|
+
t.same(JSON.parse(body), { hello: 123 })
|
|
186
|
+
})
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
test('request search querystring schema error', t => {
|
|
190
|
+
t.plan(3)
|
|
191
|
+
sget({
|
|
192
|
+
method: 'SEARCH',
|
|
193
|
+
url: `${url}/query?hello=world`
|
|
194
|
+
}, (err, response, body) => {
|
|
195
|
+
t.error(err)
|
|
196
|
+
t.equal(response.statusCode, 400)
|
|
197
|
+
t.same(JSON.parse(body), {
|
|
198
|
+
error: 'Bad Request',
|
|
199
|
+
message: 'querystring/hello must be integer',
|
|
200
|
+
statusCode: 400
|
|
201
|
+
})
|
|
202
|
+
})
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
test('request search body schema', t => {
|
|
206
|
+
t.plan(4)
|
|
207
|
+
const replyBody = { foo: 'bar', test: 5 }
|
|
208
|
+
sget({
|
|
209
|
+
method: 'SEARCH',
|
|
210
|
+
url: `${url}/body`,
|
|
211
|
+
body: JSON.stringify(replyBody),
|
|
212
|
+
headers: { 'content-type': 'application/json' }
|
|
213
|
+
}, (err, response, body) => {
|
|
214
|
+
t.error(err)
|
|
215
|
+
t.equal(response.statusCode, 200)
|
|
216
|
+
t.equal(response.headers['content-length'], '' + body.length)
|
|
217
|
+
t.same(JSON.parse(body), replyBody)
|
|
218
|
+
})
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
test('request search body schema error', t => {
|
|
222
|
+
t.plan(4)
|
|
223
|
+
sget({
|
|
224
|
+
method: 'SEARCH',
|
|
225
|
+
url: `${url}/body`,
|
|
226
|
+
body: JSON.stringify({ foo: 'bar', test: 'test' }),
|
|
227
|
+
headers: { 'content-type': 'application/json' }
|
|
228
|
+
}, (err, response, body) => {
|
|
229
|
+
t.error(err)
|
|
230
|
+
t.equal(response.statusCode, 400)
|
|
231
|
+
t.equal(response.headers['content-length'], '' + body.length)
|
|
232
|
+
t.same(JSON.parse(body), {
|
|
233
|
+
error: 'Bad Request',
|
|
234
|
+
message: 'body/test must be integer',
|
|
235
|
+
statusCode: 400
|
|
236
|
+
})
|
|
237
|
+
})
|
|
238
|
+
})
|
|
239
|
+
})
|