fastify 4.23.2 → 4.24.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 +1 -1
- package/docs/Guides/Ecosystem.md +6 -0
- package/docs/Reference/Hooks.md +1 -0
- package/docs/Reference/Plugins.md +1 -1
- package/docs/Reference/Reply.md +4 -3
- package/docs/Reference/Request.md +3 -2
- package/docs/Reference/Server.md +31 -3
- package/docs/Reference/Type-Providers.md +2 -2
- package/docs/Reference/TypeScript.md +21 -7
- package/fastify.d.ts +2 -2
- package/fastify.js +8 -1
- package/lib/contentTypeParser.js +1 -1
- package/lib/reply.js +20 -3
- package/lib/reqIdGenFactory.js +15 -9
- package/lib/request.js +1 -1
- package/lib/route.js +28 -7
- package/lib/schemas.js +3 -3
- package/lib/warnings.js +3 -1
- package/package.json +33 -33
- package/test/404s.test.js +31 -39
- package/test/async-await.test.js +1 -1
- package/test/async-dispose.test.js +21 -0
- package/test/build-certificate.js +90 -1
- package/test/close-pipelining.test.js +5 -5
- package/test/close.test.js +1 -5
- package/test/constrained-routes.test.js +127 -3
- package/test/custom-http-server.test.js +94 -91
- package/test/custom-parser.0.test.js +21 -47
- package/test/custom-parser.1.test.js +10 -732
- package/test/custom-parser.2.test.js +102 -0
- package/test/custom-parser.3.test.js +245 -0
- package/test/custom-parser.4.test.js +239 -0
- package/test/custom-parser.5.test.js +149 -0
- package/test/head.test.js +204 -0
- package/test/helper.js +30 -8
- package/test/hooks-async.test.js +163 -13
- package/test/hooks.on-listen.test.js +7 -6
- package/test/hooks.test.js +4 -15
- package/test/http2/closing.test.js +7 -15
- package/test/https/custom-https-server.test.js +43 -40
- package/test/input-validation.js +3 -3
- package/test/internals/reply.test.js +33 -4
- package/test/listen.1.test.js +101 -0
- package/test/listen.2.test.js +103 -0
- package/test/listen.3.test.js +87 -0
- package/test/listen.4.test.js +164 -0
- package/test/listen.deprecated.test.js +3 -9
- package/test/logger/instantiation.test.js +347 -0
- package/test/logger/logger-test-utils.js +47 -0
- package/test/logger/logging.test.js +406 -0
- package/test/logger/options.test.js +500 -0
- package/test/logger/request.test.js +292 -0
- package/test/logger/response.test.js +184 -0
- package/test/plugin.1.test.js +249 -0
- package/test/plugin.2.test.js +328 -0
- package/test/plugin.3.test.js +311 -0
- package/test/plugin.4.test.js +416 -0
- package/test/reply-code.test.js +64 -0
- package/test/reply-trailers.test.js +1 -2
- package/test/route.1.test.js +309 -0
- package/test/route.2.test.js +99 -0
- package/test/route.3.test.js +205 -0
- package/test/route.4.test.js +131 -0
- package/test/route.5.test.js +230 -0
- package/test/route.6.test.js +306 -0
- package/test/route.7.test.js +370 -0
- package/test/route.8.test.js +142 -0
- package/test/stream.1.test.js +108 -0
- package/test/stream.2.test.js +119 -0
- package/test/stream.3.test.js +192 -0
- package/test/stream.4.test.js +223 -0
- package/test/stream.5.test.js +194 -0
- package/test/trust-proxy.test.js +2 -4
- package/test/types/reply.test-d.ts +3 -3
- package/test/types/request.test-d.ts +9 -9
- package/test/types/type-provider.test-d.ts +89 -0
- package/test/types/using.test-d.ts +14 -0
- package/test/upgrade.test.js +3 -3
- package/types/context.d.ts +9 -2
- package/types/instance.d.ts +4 -1
- package/types/plugin.d.ts +2 -1
- package/types/reply.d.ts +2 -2
- package/types/request.d.ts +3 -3
- package/types/route.d.ts +5 -5
- package/test/listen.test.js +0 -427
- package/test/plugin.test.js +0 -1275
- package/test/route.test.js +0 -1762
- package/test/serial/logger.0.test.js +0 -866
- package/test/serial/logger.1.test.js +0 -862
- package/test/stream.test.js +0 -816
- /package/test/{serial → logger}/tap-parallel-not-ok +0 -0
package/test/reply-code.test.js
CHANGED
|
@@ -57,3 +57,67 @@ test('code should handle null/undefined/float', t => {
|
|
|
57
57
|
t.equal(res.statusCode, 404)
|
|
58
58
|
})
|
|
59
59
|
})
|
|
60
|
+
|
|
61
|
+
test('code should handle 204', t => {
|
|
62
|
+
t.plan(8)
|
|
63
|
+
|
|
64
|
+
const fastify = Fastify()
|
|
65
|
+
|
|
66
|
+
fastify.get('/204', function (request, reply) {
|
|
67
|
+
reply.status(204)
|
|
68
|
+
return null
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
fastify.get('/undefined/204', function (request, reply) {
|
|
72
|
+
reply.status(204).send({ message: 'hello' })
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
fastify.inject({
|
|
76
|
+
method: 'GET',
|
|
77
|
+
url: '/204'
|
|
78
|
+
}, (error, res) => {
|
|
79
|
+
t.error(error)
|
|
80
|
+
t.equal(res.statusCode, 204)
|
|
81
|
+
t.equal(res.payload, '')
|
|
82
|
+
t.equal(res.headers['content-length'], undefined)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
fastify.inject({
|
|
86
|
+
method: 'GET',
|
|
87
|
+
url: '/undefined/204'
|
|
88
|
+
}, (error, res) => {
|
|
89
|
+
t.error(error)
|
|
90
|
+
t.equal(res.statusCode, 204)
|
|
91
|
+
t.equal(res.payload, '')
|
|
92
|
+
t.equal(res.headers['content-length'], undefined)
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
test('code should handle onSend hook on 204', t => {
|
|
97
|
+
t.plan(5)
|
|
98
|
+
|
|
99
|
+
const fastify = Fastify()
|
|
100
|
+
fastify.addHook('onSend', async function (request, reply, payload) {
|
|
101
|
+
return {
|
|
102
|
+
...payload,
|
|
103
|
+
world: 'hello'
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
fastify.get('/204', function (request, reply) {
|
|
108
|
+
reply.status(204).send({
|
|
109
|
+
hello: 'world'
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
fastify.inject({
|
|
114
|
+
method: 'GET',
|
|
115
|
+
url: '/204'
|
|
116
|
+
}, (error, res) => {
|
|
117
|
+
t.error(error)
|
|
118
|
+
t.equal(res.statusCode, 204)
|
|
119
|
+
t.equal(res.payload, '')
|
|
120
|
+
t.equal(res.headers['content-length'], undefined)
|
|
121
|
+
t.equal(res.headers['content-type'], undefined)
|
|
122
|
+
})
|
|
123
|
+
})
|
|
@@ -5,8 +5,7 @@ const test = t.test
|
|
|
5
5
|
const Fastify = require('..')
|
|
6
6
|
const { Readable } = require('node:stream')
|
|
7
7
|
const { createHash } = require('node:crypto')
|
|
8
|
-
const {
|
|
9
|
-
const sleep = promisify(setTimeout)
|
|
8
|
+
const { sleep } = require('./helper')
|
|
10
9
|
|
|
11
10
|
test('send trailers when payload is empty string', t => {
|
|
12
11
|
t.plan(5)
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const sget = require('simple-get').concat
|
|
6
|
+
const Fastify = require('..')
|
|
7
|
+
const {
|
|
8
|
+
FST_ERR_INSTANCE_ALREADY_LISTENING,
|
|
9
|
+
FST_ERR_ROUTE_METHOD_INVALID
|
|
10
|
+
} = require('../lib/errors')
|
|
11
|
+
const { getServerUrl } = require('./helper')
|
|
12
|
+
|
|
13
|
+
test('route', t => {
|
|
14
|
+
t.plan(10)
|
|
15
|
+
const test = t.test
|
|
16
|
+
|
|
17
|
+
test('route - get', t => {
|
|
18
|
+
t.plan(4)
|
|
19
|
+
|
|
20
|
+
const fastify = Fastify()
|
|
21
|
+
t.doesNotThrow(() =>
|
|
22
|
+
fastify.route({
|
|
23
|
+
method: 'GET',
|
|
24
|
+
url: '/',
|
|
25
|
+
schema: {
|
|
26
|
+
response: {
|
|
27
|
+
'2xx': {
|
|
28
|
+
type: 'object',
|
|
29
|
+
properties: {
|
|
30
|
+
hello: {
|
|
31
|
+
type: 'string'
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
handler: function (req, reply) {
|
|
38
|
+
reply.send({ hello: 'world' })
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
fastify.listen({ port: 0 }, function (err) {
|
|
44
|
+
if (err) t.error(err)
|
|
45
|
+
t.teardown(() => { fastify.close() })
|
|
46
|
+
sget({
|
|
47
|
+
method: 'GET',
|
|
48
|
+
url: getServerUrl(fastify) + '/'
|
|
49
|
+
}, (err, response, body) => {
|
|
50
|
+
t.error(err)
|
|
51
|
+
t.equal(response.statusCode, 200)
|
|
52
|
+
t.same(JSON.parse(body), { hello: 'world' })
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test('missing schema - route', t => {
|
|
58
|
+
t.plan(4)
|
|
59
|
+
|
|
60
|
+
const fastify = Fastify()
|
|
61
|
+
t.doesNotThrow(() =>
|
|
62
|
+
fastify.route({
|
|
63
|
+
method: 'GET',
|
|
64
|
+
url: '/missing',
|
|
65
|
+
handler: function (req, reply) {
|
|
66
|
+
reply.send({ hello: 'world' })
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
fastify.listen({ port: 0 }, function (err) {
|
|
72
|
+
if (err) t.error(err)
|
|
73
|
+
t.teardown(() => { fastify.close() })
|
|
74
|
+
sget({
|
|
75
|
+
method: 'GET',
|
|
76
|
+
url: getServerUrl(fastify) + '/missing'
|
|
77
|
+
}, (err, response, body) => {
|
|
78
|
+
t.error(err)
|
|
79
|
+
t.equal(response.statusCode, 200)
|
|
80
|
+
t.same(JSON.parse(body), { hello: 'world' })
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('invalid handler attribute - route', t => {
|
|
86
|
+
t.plan(1)
|
|
87
|
+
|
|
88
|
+
const fastify = Fastify()
|
|
89
|
+
t.throws(() => fastify.get('/', { handler: 'not a function' }, () => { }))
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
test('Add Multiple methods per route all uppercase', t => {
|
|
93
|
+
t.plan(7)
|
|
94
|
+
|
|
95
|
+
const fastify = Fastify()
|
|
96
|
+
t.doesNotThrow(() =>
|
|
97
|
+
fastify.route({
|
|
98
|
+
method: ['GET', 'DELETE'],
|
|
99
|
+
url: '/multiple',
|
|
100
|
+
handler: function (req, reply) {
|
|
101
|
+
reply.send({ hello: 'world' })
|
|
102
|
+
}
|
|
103
|
+
}))
|
|
104
|
+
|
|
105
|
+
fastify.listen({ port: 0 }, function (err) {
|
|
106
|
+
if (err) t.error(err)
|
|
107
|
+
t.teardown(() => { fastify.close() })
|
|
108
|
+
sget({
|
|
109
|
+
method: 'GET',
|
|
110
|
+
url: getServerUrl(fastify) + '/multiple'
|
|
111
|
+
}, (err, response, body) => {
|
|
112
|
+
t.error(err)
|
|
113
|
+
t.equal(response.statusCode, 200)
|
|
114
|
+
t.same(JSON.parse(body), { hello: 'world' })
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
sget({
|
|
118
|
+
method: 'DELETE',
|
|
119
|
+
url: getServerUrl(fastify) + '/multiple'
|
|
120
|
+
}, (err, response, body) => {
|
|
121
|
+
t.error(err)
|
|
122
|
+
t.equal(response.statusCode, 200)
|
|
123
|
+
t.same(JSON.parse(body), { hello: 'world' })
|
|
124
|
+
})
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
test('Add Multiple methods per route all lowercase', t => {
|
|
129
|
+
t.plan(7)
|
|
130
|
+
|
|
131
|
+
const fastify = Fastify()
|
|
132
|
+
t.doesNotThrow(() =>
|
|
133
|
+
fastify.route({
|
|
134
|
+
method: ['get', 'delete'],
|
|
135
|
+
url: '/multiple',
|
|
136
|
+
handler: function (req, reply) {
|
|
137
|
+
reply.send({ hello: 'world' })
|
|
138
|
+
}
|
|
139
|
+
}))
|
|
140
|
+
|
|
141
|
+
fastify.listen({ port: 0 }, function (err) {
|
|
142
|
+
if (err) t.error(err)
|
|
143
|
+
t.teardown(() => { fastify.close() })
|
|
144
|
+
sget({
|
|
145
|
+
method: 'GET',
|
|
146
|
+
url: getServerUrl(fastify) + '/multiple'
|
|
147
|
+
}, (err, response, body) => {
|
|
148
|
+
t.error(err)
|
|
149
|
+
t.equal(response.statusCode, 200)
|
|
150
|
+
t.same(JSON.parse(body), { hello: 'world' })
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
sget({
|
|
154
|
+
method: 'DELETE',
|
|
155
|
+
url: getServerUrl(fastify) + '/multiple'
|
|
156
|
+
}, (err, response, body) => {
|
|
157
|
+
t.error(err)
|
|
158
|
+
t.equal(response.statusCode, 200)
|
|
159
|
+
t.same(JSON.parse(body), { hello: 'world' })
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
test('Add Multiple methods per route mixed uppercase and lowercase', t => {
|
|
165
|
+
t.plan(7)
|
|
166
|
+
|
|
167
|
+
const fastify = Fastify()
|
|
168
|
+
t.doesNotThrow(() =>
|
|
169
|
+
fastify.route({
|
|
170
|
+
method: ['GET', 'delete'],
|
|
171
|
+
url: '/multiple',
|
|
172
|
+
handler: function (req, reply) {
|
|
173
|
+
reply.send({ hello: 'world' })
|
|
174
|
+
}
|
|
175
|
+
}))
|
|
176
|
+
|
|
177
|
+
fastify.listen({ port: 0 }, function (err) {
|
|
178
|
+
if (err) t.error(err)
|
|
179
|
+
t.teardown(() => { fastify.close() })
|
|
180
|
+
sget({
|
|
181
|
+
method: 'GET',
|
|
182
|
+
url: getServerUrl(fastify) + '/multiple'
|
|
183
|
+
}, (err, response, body) => {
|
|
184
|
+
t.error(err)
|
|
185
|
+
t.equal(response.statusCode, 200)
|
|
186
|
+
t.same(JSON.parse(body), { hello: 'world' })
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
sget({
|
|
190
|
+
method: 'DELETE',
|
|
191
|
+
url: getServerUrl(fastify) + '/multiple'
|
|
192
|
+
}, (err, response, body) => {
|
|
193
|
+
t.error(err)
|
|
194
|
+
t.equal(response.statusCode, 200)
|
|
195
|
+
t.same(JSON.parse(body), { hello: 'world' })
|
|
196
|
+
})
|
|
197
|
+
})
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
test('Add invalid Multiple methods per route', t => {
|
|
201
|
+
t.plan(1)
|
|
202
|
+
|
|
203
|
+
const fastify = Fastify()
|
|
204
|
+
t.throws(() =>
|
|
205
|
+
fastify.route({
|
|
206
|
+
method: ['GET', 1],
|
|
207
|
+
url: '/invalid-method',
|
|
208
|
+
handler: function (req, reply) {
|
|
209
|
+
reply.send({ hello: 'world' })
|
|
210
|
+
}
|
|
211
|
+
}), new FST_ERR_ROUTE_METHOD_INVALID())
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
test('Add method', t => {
|
|
215
|
+
t.plan(1)
|
|
216
|
+
|
|
217
|
+
const fastify = Fastify()
|
|
218
|
+
t.throws(() =>
|
|
219
|
+
fastify.route({
|
|
220
|
+
method: 1,
|
|
221
|
+
url: '/invalid-method',
|
|
222
|
+
handler: function (req, reply) {
|
|
223
|
+
reply.send({ hello: 'world' })
|
|
224
|
+
}
|
|
225
|
+
}), new FST_ERR_ROUTE_METHOD_INVALID())
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
test('Add additional multiple methods to existing route', t => {
|
|
229
|
+
t.plan(7)
|
|
230
|
+
|
|
231
|
+
const fastify = Fastify()
|
|
232
|
+
t.doesNotThrow(() => {
|
|
233
|
+
fastify.get('/add-multiple', function (req, reply) {
|
|
234
|
+
reply.send({ hello: 'Bob!' })
|
|
235
|
+
})
|
|
236
|
+
fastify.route({
|
|
237
|
+
method: ['PUT', 'DELETE'],
|
|
238
|
+
url: '/add-multiple',
|
|
239
|
+
handler: function (req, reply) {
|
|
240
|
+
reply.send({ hello: 'world' })
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
fastify.listen({ port: 0 }, function (err) {
|
|
246
|
+
if (err) t.error(err)
|
|
247
|
+
t.teardown(() => { fastify.close() })
|
|
248
|
+
sget({
|
|
249
|
+
method: 'PUT',
|
|
250
|
+
url: getServerUrl(fastify) + '/add-multiple'
|
|
251
|
+
}, (err, response, body) => {
|
|
252
|
+
t.error(err)
|
|
253
|
+
t.equal(response.statusCode, 200)
|
|
254
|
+
t.same(JSON.parse(body), { hello: 'world' })
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
sget({
|
|
258
|
+
method: 'DELETE',
|
|
259
|
+
url: getServerUrl(fastify) + '/add-multiple'
|
|
260
|
+
}, (err, response, body) => {
|
|
261
|
+
t.error(err)
|
|
262
|
+
t.equal(response.statusCode, 200)
|
|
263
|
+
t.same(JSON.parse(body), { hello: 'world' })
|
|
264
|
+
})
|
|
265
|
+
})
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
test('cannot add another route after binding', t => {
|
|
269
|
+
t.plan(1)
|
|
270
|
+
|
|
271
|
+
const fastify = Fastify()
|
|
272
|
+
|
|
273
|
+
fastify.listen({ port: 0 }, function (err) {
|
|
274
|
+
if (err) t.error(err)
|
|
275
|
+
t.teardown(() => { fastify.close() })
|
|
276
|
+
|
|
277
|
+
t.throws(() => fastify.route({
|
|
278
|
+
method: 'GET',
|
|
279
|
+
url: '/another-get-route',
|
|
280
|
+
handler: function (req, reply) {
|
|
281
|
+
reply.send({ hello: 'world' })
|
|
282
|
+
}
|
|
283
|
+
}), new FST_ERR_INSTANCE_ALREADY_LISTENING('Cannot add route!'))
|
|
284
|
+
})
|
|
285
|
+
})
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
test('invalid schema - route', t => {
|
|
289
|
+
t.plan(3)
|
|
290
|
+
|
|
291
|
+
const fastify = Fastify()
|
|
292
|
+
fastify.route({
|
|
293
|
+
handler: () => { },
|
|
294
|
+
method: 'GET',
|
|
295
|
+
url: '/invalid',
|
|
296
|
+
schema: {
|
|
297
|
+
querystring: {
|
|
298
|
+
id: 'string'
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
})
|
|
302
|
+
fastify.after(err => {
|
|
303
|
+
t.notOk(err, 'the error is throw on preReady')
|
|
304
|
+
})
|
|
305
|
+
fastify.ready(err => {
|
|
306
|
+
t.equal(err.code, 'FST_ERR_SCH_VALIDATION_BUILD')
|
|
307
|
+
t.match(err.message, /Failed building the validation schema for GET: \/invalid/)
|
|
308
|
+
})
|
|
309
|
+
})
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const Fastify = require('../fastify')
|
|
6
|
+
|
|
7
|
+
test('same route definition object on multiple prefixes', async t => {
|
|
8
|
+
t.plan(2)
|
|
9
|
+
|
|
10
|
+
const routeObject = {
|
|
11
|
+
handler: () => { },
|
|
12
|
+
method: 'GET',
|
|
13
|
+
url: '/simple'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const fastify = Fastify({ exposeHeadRoutes: false })
|
|
17
|
+
|
|
18
|
+
fastify.register(async function (f) {
|
|
19
|
+
f.addHook('onRoute', (routeOptions) => {
|
|
20
|
+
t.equal(routeOptions.url, '/v1/simple')
|
|
21
|
+
})
|
|
22
|
+
f.route(routeObject)
|
|
23
|
+
}, { prefix: '/v1' })
|
|
24
|
+
fastify.register(async function (f) {
|
|
25
|
+
f.addHook('onRoute', (routeOptions) => {
|
|
26
|
+
t.equal(routeOptions.url, '/v2/simple')
|
|
27
|
+
})
|
|
28
|
+
f.route(routeObject)
|
|
29
|
+
}, { prefix: '/v2' })
|
|
30
|
+
|
|
31
|
+
await fastify.ready()
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('path can be specified in place of uri', t => {
|
|
35
|
+
t.plan(3)
|
|
36
|
+
const fastify = Fastify()
|
|
37
|
+
|
|
38
|
+
fastify.route({
|
|
39
|
+
method: 'GET',
|
|
40
|
+
path: '/path',
|
|
41
|
+
handler: function (req, reply) {
|
|
42
|
+
reply.send({ hello: 'world' })
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const reqOpts = {
|
|
47
|
+
method: 'GET',
|
|
48
|
+
url: '/path'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
fastify.inject(reqOpts, (err, res) => {
|
|
52
|
+
t.error(err)
|
|
53
|
+
t.equal(res.statusCode, 200)
|
|
54
|
+
t.same(JSON.parse(res.payload), { hello: 'world' })
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('invalid bodyLimit option - route', t => {
|
|
59
|
+
t.plan(2)
|
|
60
|
+
const fastify = Fastify()
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
fastify.route({
|
|
64
|
+
bodyLimit: false,
|
|
65
|
+
method: 'PUT',
|
|
66
|
+
handler: () => null
|
|
67
|
+
})
|
|
68
|
+
t.fail('bodyLimit must be an integer')
|
|
69
|
+
} catch (err) {
|
|
70
|
+
t.equal(err.message, "'bodyLimit' option must be an integer > 0. Got 'false'")
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
fastify.post('/url', { bodyLimit: 10000.1 }, () => null)
|
|
75
|
+
t.fail('bodyLimit must be an integer')
|
|
76
|
+
} catch (err) {
|
|
77
|
+
t.equal(err.message, "'bodyLimit' option must be an integer > 0. Got '10000.1'")
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test('handler function in options of shorthand route should works correctly', t => {
|
|
82
|
+
t.plan(3)
|
|
83
|
+
|
|
84
|
+
const fastify = Fastify()
|
|
85
|
+
fastify.get('/foo', {
|
|
86
|
+
handler: (req, reply) => {
|
|
87
|
+
reply.send({ hello: 'world' })
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
fastify.inject({
|
|
92
|
+
method: 'GET',
|
|
93
|
+
url: '/foo'
|
|
94
|
+
}, (err, res) => {
|
|
95
|
+
t.error(err)
|
|
96
|
+
t.equal(res.statusCode, 200)
|
|
97
|
+
t.same(JSON.parse(res.payload), { hello: 'world' })
|
|
98
|
+
})
|
|
99
|
+
})
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const joi = require('joi')
|
|
6
|
+
const Fastify = require('..')
|
|
7
|
+
|
|
8
|
+
test('does not mutate joi schemas', t => {
|
|
9
|
+
t.plan(4)
|
|
10
|
+
|
|
11
|
+
const fastify = Fastify()
|
|
12
|
+
function validatorCompiler ({ schema, method, url, httpPart }) {
|
|
13
|
+
// Needed to extract the params part,
|
|
14
|
+
// without the JSON-schema encapsulation
|
|
15
|
+
// that is automatically added by the short
|
|
16
|
+
// form of params.
|
|
17
|
+
schema = joi.object(schema.properties)
|
|
18
|
+
|
|
19
|
+
return validateHttpData
|
|
20
|
+
|
|
21
|
+
function validateHttpData (data) {
|
|
22
|
+
return schema.validate(data)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
fastify.setValidatorCompiler(validatorCompiler)
|
|
27
|
+
|
|
28
|
+
fastify.route({
|
|
29
|
+
path: '/foo/:an_id',
|
|
30
|
+
method: 'GET',
|
|
31
|
+
schema: {
|
|
32
|
+
params: { an_id: joi.number() }
|
|
33
|
+
},
|
|
34
|
+
handler (req, res) {
|
|
35
|
+
t.same(req.params, { an_id: 42 })
|
|
36
|
+
res.send({ hello: 'world' })
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
fastify.inject({
|
|
41
|
+
method: 'GET',
|
|
42
|
+
url: '/foo/42'
|
|
43
|
+
}, (err, result) => {
|
|
44
|
+
t.error(err)
|
|
45
|
+
t.equal(result.statusCode, 200)
|
|
46
|
+
t.same(JSON.parse(result.payload), { hello: 'world' })
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('multiple routes with one schema', t => {
|
|
51
|
+
t.plan(2)
|
|
52
|
+
|
|
53
|
+
const fastify = Fastify()
|
|
54
|
+
|
|
55
|
+
const schema = {
|
|
56
|
+
query: {
|
|
57
|
+
id: { type: 'number' }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fastify.route({
|
|
62
|
+
schema,
|
|
63
|
+
method: 'GET',
|
|
64
|
+
path: '/first/:id',
|
|
65
|
+
handler (req, res) {
|
|
66
|
+
res.send({ hello: 'world' })
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
fastify.route({
|
|
71
|
+
schema,
|
|
72
|
+
method: 'GET',
|
|
73
|
+
path: '/second/:id',
|
|
74
|
+
handler (req, res) {
|
|
75
|
+
res.send({ hello: 'world' })
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
fastify.ready(error => {
|
|
80
|
+
t.error(error)
|
|
81
|
+
t.same(schema, schema)
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('route error handler overrides default error handler', t => {
|
|
86
|
+
t.plan(4)
|
|
87
|
+
|
|
88
|
+
const fastify = Fastify()
|
|
89
|
+
|
|
90
|
+
const customRouteErrorHandler = (error, request, reply) => {
|
|
91
|
+
t.equal(error.message, 'Wrong Pot Error')
|
|
92
|
+
|
|
93
|
+
reply.code(418).send({
|
|
94
|
+
message: 'Make a brew',
|
|
95
|
+
statusCode: 418,
|
|
96
|
+
error: 'Wrong Pot Error'
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
fastify.route({
|
|
101
|
+
method: 'GET',
|
|
102
|
+
path: '/coffee',
|
|
103
|
+
handler: (req, res) => {
|
|
104
|
+
res.send(new Error('Wrong Pot Error'))
|
|
105
|
+
},
|
|
106
|
+
errorHandler: customRouteErrorHandler
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
fastify.inject({
|
|
110
|
+
method: 'GET',
|
|
111
|
+
url: '/coffee'
|
|
112
|
+
}, (error, res) => {
|
|
113
|
+
t.error(error)
|
|
114
|
+
t.equal(res.statusCode, 418)
|
|
115
|
+
t.same(JSON.parse(res.payload), {
|
|
116
|
+
message: 'Make a brew',
|
|
117
|
+
statusCode: 418,
|
|
118
|
+
error: 'Wrong Pot Error'
|
|
119
|
+
})
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test('route error handler does not affect other routes', t => {
|
|
124
|
+
t.plan(3)
|
|
125
|
+
|
|
126
|
+
const fastify = Fastify()
|
|
127
|
+
|
|
128
|
+
const customRouteErrorHandler = (error, request, reply) => {
|
|
129
|
+
t.equal(error.message, 'Wrong Pot Error')
|
|
130
|
+
|
|
131
|
+
reply.code(418).send({
|
|
132
|
+
message: 'Make a brew',
|
|
133
|
+
statusCode: 418,
|
|
134
|
+
error: 'Wrong Pot Error'
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
fastify.route({
|
|
139
|
+
method: 'GET',
|
|
140
|
+
path: '/coffee',
|
|
141
|
+
handler: (req, res) => {
|
|
142
|
+
res.send(new Error('Wrong Pot Error'))
|
|
143
|
+
},
|
|
144
|
+
errorHandler: customRouteErrorHandler
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
fastify.route({
|
|
148
|
+
method: 'GET',
|
|
149
|
+
path: '/tea',
|
|
150
|
+
handler: (req, res) => {
|
|
151
|
+
res.send(new Error('No tea today'))
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
fastify.inject({
|
|
156
|
+
method: 'GET',
|
|
157
|
+
url: '/tea'
|
|
158
|
+
}, (error, res) => {
|
|
159
|
+
t.error(error)
|
|
160
|
+
t.equal(res.statusCode, 500)
|
|
161
|
+
t.same(JSON.parse(res.payload), {
|
|
162
|
+
message: 'No tea today',
|
|
163
|
+
statusCode: 500,
|
|
164
|
+
error: 'Internal Server Error'
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
test('async error handler for a route', t => {
|
|
170
|
+
t.plan(4)
|
|
171
|
+
|
|
172
|
+
const fastify = Fastify()
|
|
173
|
+
|
|
174
|
+
const customRouteErrorHandler = async (error, request, reply) => {
|
|
175
|
+
t.equal(error.message, 'Delayed Pot Error')
|
|
176
|
+
reply.code(418)
|
|
177
|
+
return {
|
|
178
|
+
message: 'Make a brew sometime later',
|
|
179
|
+
statusCode: 418,
|
|
180
|
+
error: 'Delayed Pot Error'
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
fastify.route({
|
|
185
|
+
method: 'GET',
|
|
186
|
+
path: '/late-coffee',
|
|
187
|
+
handler: (req, res) => {
|
|
188
|
+
res.send(new Error('Delayed Pot Error'))
|
|
189
|
+
},
|
|
190
|
+
errorHandler: customRouteErrorHandler
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
fastify.inject({
|
|
194
|
+
method: 'GET',
|
|
195
|
+
url: '/late-coffee'
|
|
196
|
+
}, (error, res) => {
|
|
197
|
+
t.error(error)
|
|
198
|
+
t.equal(res.statusCode, 418)
|
|
199
|
+
t.same(JSON.parse(res.payload), {
|
|
200
|
+
message: 'Make a brew sometime later',
|
|
201
|
+
statusCode: 418,
|
|
202
|
+
error: 'Delayed Pot Error'
|
|
203
|
+
})
|
|
204
|
+
})
|
|
205
|
+
})
|