fastify 4.6.0 → 4.8.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 +20 -9
- package/docs/Guides/Plugins-Guide.md +44 -0
- package/docs/Guides/Testing.md +50 -17
- package/docs/Reference/Errors.md +205 -60
- package/docs/Reference/Hooks.md +27 -0
- package/docs/Reference/Reply.md +5 -5
- package/docs/Reference/Request.md +19 -6
- package/docs/Reference/Routes.md +56 -2
- package/docs/Reference/Server.md +3 -0
- package/docs/Reference/Type-Providers.md +3 -3
- package/fastify.d.ts +6 -0
- package/fastify.js +58 -25
- package/lib/contentTypeParser.js +10 -9
- package/lib/context.js +27 -3
- package/lib/error-handler.js +7 -3
- package/lib/errors.js +39 -28
- package/lib/handleRequest.js +15 -13
- package/lib/reply.js +42 -34
- package/lib/request.js +36 -18
- package/lib/route.js +22 -11
- package/lib/schema-controller.js +7 -1
- package/lib/server.js +2 -2
- 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/constrained-routes.test.js +114 -0
- package/test/context-config.test.js +2 -1
- package/test/handler-context.test.js +12 -30
- 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/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 +89 -68
- package/test/schema-feature.test.js +25 -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 +5 -1
- package/types/errors.d.ts +53 -0
- package/types/request.d.ts +9 -3
|
@@ -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 = {
|
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,13 @@
|
|
|
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
|
-
const {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (address === '::1') {
|
|
11
|
-
return `http://[${address}]:${port}`
|
|
12
|
-
} else {
|
|
13
|
-
return `http://${address}:${port}`
|
|
14
|
-
}
|
|
15
|
-
}
|
|
5
|
+
const {
|
|
6
|
+
FST_ERR_BAD_URL,
|
|
7
|
+
FST_ERR_ASYNC_CONSTRAINT
|
|
8
|
+
} = require('../lib/errors')
|
|
16
9
|
|
|
17
|
-
test('Should honor ignoreTrailingSlash option', t => {
|
|
10
|
+
test('Should honor ignoreTrailingSlash option', async t => {
|
|
18
11
|
t.plan(4)
|
|
19
12
|
const fastify = Fastify({
|
|
20
13
|
ignoreTrailingSlash: true
|
|
@@ -24,27 +17,16 @@ test('Should honor ignoreTrailingSlash option', t => {
|
|
|
24
17
|
res.send('test')
|
|
25
18
|
})
|
|
26
19
|
|
|
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
|
-
})
|
|
20
|
+
let res = await fastify.inject('/test')
|
|
21
|
+
t.equal(res.statusCode, 200)
|
|
22
|
+
t.equal(res.payload.toString(), 'test')
|
|
38
23
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
t.equal(data.toString(), 'test')
|
|
43
|
-
})
|
|
44
|
-
})
|
|
24
|
+
res = await fastify.inject('/test/')
|
|
25
|
+
t.equal(res.statusCode, 200)
|
|
26
|
+
t.equal(res.payload.toString(), 'test')
|
|
45
27
|
})
|
|
46
28
|
|
|
47
|
-
test('Should honor ignoreDuplicateSlashes option', t => {
|
|
29
|
+
test('Should honor ignoreDuplicateSlashes option', async t => {
|
|
48
30
|
t.plan(4)
|
|
49
31
|
const fastify = Fastify({
|
|
50
32
|
ignoreDuplicateSlashes: true
|
|
@@ -54,27 +36,16 @@ test('Should honor ignoreDuplicateSlashes option', t => {
|
|
|
54
36
|
res.send('test')
|
|
55
37
|
})
|
|
56
38
|
|
|
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
|
-
})
|
|
39
|
+
let res = await fastify.inject('/test/test/test')
|
|
40
|
+
t.equal(res.statusCode, 200)
|
|
41
|
+
t.equal(res.payload.toString(), 'test')
|
|
68
42
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
t.equal(data.toString(), 'test')
|
|
73
|
-
})
|
|
74
|
-
})
|
|
43
|
+
res = await fastify.inject('/test//test///test')
|
|
44
|
+
t.equal(res.statusCode, 200)
|
|
45
|
+
t.equal(res.payload.toString(), 'test')
|
|
75
46
|
})
|
|
76
47
|
|
|
77
|
-
test('Should honor ignoreTrailingSlash and ignoreDuplicateSlashes options', t => {
|
|
48
|
+
test('Should honor ignoreTrailingSlash and ignoreDuplicateSlashes options', async t => {
|
|
78
49
|
t.plan(4)
|
|
79
50
|
const fastify = Fastify({
|
|
80
51
|
ignoreTrailingSlash: true,
|
|
@@ -85,24 +56,13 @@ test('Should honor ignoreTrailingSlash and ignoreDuplicateSlashes options', t =>
|
|
|
85
56
|
res.send('test')
|
|
86
57
|
})
|
|
87
58
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const baseUrl = getUrl(fastify)
|
|
93
|
-
|
|
94
|
-
sget.concat(baseUrl + '/test/test/test/', (err, res, data) => {
|
|
95
|
-
if (err) t.threw(err)
|
|
96
|
-
t.equal(res.statusCode, 200)
|
|
97
|
-
t.equal(data.toString(), 'test')
|
|
98
|
-
})
|
|
59
|
+
let res = await fastify.inject('/test/test/test/')
|
|
60
|
+
t.equal(res.statusCode, 200)
|
|
61
|
+
t.equal(res.payload.toString(), 'test')
|
|
99
62
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
t.equal(data.toString(), 'test')
|
|
104
|
-
})
|
|
105
|
-
})
|
|
63
|
+
res = await fastify.inject('/test//test///test//')
|
|
64
|
+
t.equal(res.statusCode, 200)
|
|
65
|
+
t.equal(res.payload.toString(), 'test')
|
|
106
66
|
})
|
|
107
67
|
|
|
108
68
|
test('Should honor maxParamLength option', t => {
|
|
@@ -131,12 +91,22 @@ test('Should honor maxParamLength option', t => {
|
|
|
131
91
|
})
|
|
132
92
|
|
|
133
93
|
test('Should expose router options via getters on request and reply', t => {
|
|
134
|
-
t.plan(
|
|
94
|
+
t.plan(10)
|
|
135
95
|
const fastify = Fastify()
|
|
96
|
+
const expectedSchema = {
|
|
97
|
+
params: {
|
|
98
|
+
id: { type: 'integer' }
|
|
99
|
+
}
|
|
100
|
+
}
|
|
136
101
|
|
|
137
|
-
fastify.get('/test/:id',
|
|
102
|
+
fastify.get('/test/:id', {
|
|
103
|
+
schema: expectedSchema
|
|
104
|
+
}, (req, reply) => {
|
|
138
105
|
t.equal(reply.context.config.url, '/test/:id')
|
|
139
106
|
t.equal(reply.context.config.method, 'GET')
|
|
107
|
+
t.equal(req.routeConfig.url, '/test/:id')
|
|
108
|
+
t.equal(req.routeConfig.method, 'GET')
|
|
109
|
+
t.same(req.routeSchema, expectedSchema)
|
|
140
110
|
t.equal(req.routerPath, '/test/:id')
|
|
141
111
|
t.equal(req.routerMethod, 'GET')
|
|
142
112
|
t.equal(req.is404, false)
|
|
@@ -170,7 +140,7 @@ test('Should set is404 flag for unmatched paths', t => {
|
|
|
170
140
|
})
|
|
171
141
|
})
|
|
172
142
|
|
|
173
|
-
test('Should honor frameworkErrors option', t => {
|
|
143
|
+
test('Should honor frameworkErrors option - FST_ERR_BAD_URL', t => {
|
|
174
144
|
t.plan(3)
|
|
175
145
|
const fastify = Fastify({
|
|
176
146
|
frameworkErrors: function (err, req, res) {
|
|
@@ -198,3 +168,54 @@ test('Should honor frameworkErrors option', t => {
|
|
|
198
168
|
}
|
|
199
169
|
)
|
|
200
170
|
})
|
|
171
|
+
|
|
172
|
+
test('Should honor frameworkErrors option - FST_ERR_ASYNC_CONSTRAINT', t => {
|
|
173
|
+
t.plan(3)
|
|
174
|
+
|
|
175
|
+
const constraint = {
|
|
176
|
+
name: 'secret',
|
|
177
|
+
storage: function () {
|
|
178
|
+
const secrets = {}
|
|
179
|
+
return {
|
|
180
|
+
get: (secret) => { return secrets[secret] || null },
|
|
181
|
+
set: (secret, store) => { secrets[secret] = store }
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
deriveConstraint: (req, ctx, done) => {
|
|
185
|
+
done(Error('kaboom'))
|
|
186
|
+
},
|
|
187
|
+
validate () { return true }
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const fastify = Fastify({
|
|
191
|
+
frameworkErrors: function (err, req, res) {
|
|
192
|
+
if (err instanceof FST_ERR_ASYNC_CONSTRAINT) {
|
|
193
|
+
t.ok(true)
|
|
194
|
+
} else {
|
|
195
|
+
t.fail()
|
|
196
|
+
}
|
|
197
|
+
res.send(`${err.message} - ${err.code}`)
|
|
198
|
+
},
|
|
199
|
+
constraints: { secret: constraint }
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
fastify.route({
|
|
203
|
+
method: 'GET',
|
|
204
|
+
url: '/',
|
|
205
|
+
constraints: { secret: 'alpha' },
|
|
206
|
+
handler: (req, reply) => {
|
|
207
|
+
reply.send({ hello: 'from alpha' })
|
|
208
|
+
}
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
fastify.inject(
|
|
212
|
+
{
|
|
213
|
+
method: 'GET',
|
|
214
|
+
url: '/'
|
|
215
|
+
},
|
|
216
|
+
(err, res) => {
|
|
217
|
+
t.error(err)
|
|
218
|
+
t.equal(res.body, 'Unexpected error from async constraint - FST_ERR_ASYNC_CONSTRAINT')
|
|
219
|
+
}
|
|
220
|
+
)
|
|
221
|
+
})
|
|
@@ -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
|
+
})
|
|
@@ -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
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const Fastify = require('..')
|
|
6
|
+
|
|
7
|
+
test('listen should accept null port', t => {
|
|
8
|
+
t.plan(1)
|
|
9
|
+
|
|
10
|
+
const fastify = Fastify()
|
|
11
|
+
t.teardown(fastify.close.bind(fastify))
|
|
12
|
+
fastify.listen({ port: null }, (err) => {
|
|
13
|
+
t.error(err)
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test('listen should accept undefined port', t => {
|
|
18
|
+
t.plan(1)
|
|
19
|
+
|
|
20
|
+
const fastify = Fastify()
|
|
21
|
+
t.teardown(fastify.close.bind(fastify))
|
|
22
|
+
fastify.listen({ port: undefined }, (err) => {
|
|
23
|
+
t.error(err)
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('listen should accept stringified number port', t => {
|
|
28
|
+
t.plan(1)
|
|
29
|
+
|
|
30
|
+
const fastify = Fastify()
|
|
31
|
+
t.teardown(fastify.close.bind(fastify))
|
|
32
|
+
fastify.listen({ port: '1234' }, (err) => {
|
|
33
|
+
t.error(err)
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test('listen should reject string port', async (t) => {
|
|
38
|
+
t.plan(2)
|
|
39
|
+
|
|
40
|
+
const fastify = Fastify()
|
|
41
|
+
t.teardown(fastify.close.bind(fastify))
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
await fastify.listen({ port: 'hello-world' })
|
|
45
|
+
} catch (error) {
|
|
46
|
+
t.same(error.message, 'options.port should be >= 0 and < 65536. Received hello-world.')
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
await fastify.listen({ port: '1234hello' })
|
|
51
|
+
} catch (error) {
|
|
52
|
+
t.same(error.message, 'options.port should be >= 0 and < 65536. Received 1234hello.')
|
|
53
|
+
}
|
|
54
|
+
})
|