fastify 2.4.1 → 2.7.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/SECURITY.md +33 -0
- package/build/build-validation.js +1 -1
- package/docs/Decorators.md +2 -2
- package/docs/Ecosystem.md +5 -1
- package/docs/Fluent-Schema.md +5 -7
- package/docs/Hooks.md +40 -40
- package/docs/Logging.md +15 -3
- package/docs/Plugins-Guide.md +21 -21
- package/docs/Plugins.md +11 -11
- package/docs/Reply.md +14 -7
- package/docs/Routes.md +6 -6
- package/docs/Server.md +40 -19
- package/docs/Serverless.md +127 -28
- package/docs/Validation-and-Serialization.md +15 -12
- package/fastify.d.ts +22 -14
- package/fastify.js +21 -0
- package/lib/context.js +5 -4
- package/lib/decorate.js +2 -0
- package/lib/errors.js +1 -0
- package/lib/handleRequest.js +2 -2
- package/lib/reply.js +23 -6
- package/lib/request.js +2 -2
- package/lib/route.js +24 -15
- package/lib/schemas.js +24 -3
- package/lib/symbols.js +1 -0
- package/lib/validation.js +19 -0
- package/package.json +19 -18
- package/test/async-await.js +1 -1
- package/test/close-pipelining.test.js +43 -2
- package/test/close.test.js +69 -12
- package/test/content-length.test.js +2 -2
- package/test/decorator.test.js +2 -0
- package/test/fluent-schema.js +54 -0
- package/test/hooks-async.js +80 -1
- package/test/hooks.test.js +4 -4
- package/test/http2/closing.js +86 -33
- package/test/input-validation.test.js +1 -1
- package/test/internals/decorator.test.js +2 -0
- package/test/internals/initialConfig.test.js +1 -1
- package/test/internals/reply.test.js +276 -1
- package/test/internals/validation.test.js +57 -0
- package/test/logger.test.js +33 -1
- package/test/nullable-validation.test.js +52 -0
- package/test/plugin.test.js +2 -0
- package/test/register.test.js +2 -0
- package/test/route-prefix.test.js +31 -0
- package/test/route.test.js +35 -0
- package/test/shared-schemas.test.js +3 -3
- package/test/types/index.ts +33 -2
- package/test/versioned-routes.test.js +3 -3
package/test/fluent-schema.js
CHANGED
|
@@ -120,6 +120,60 @@ function fluentSchemaTest (t) {
|
|
|
120
120
|
|
|
121
121
|
fastify.ready(t.error)
|
|
122
122
|
})
|
|
123
|
+
|
|
124
|
+
test('Should call valueOf internally', t => {
|
|
125
|
+
t.plan(1)
|
|
126
|
+
|
|
127
|
+
const fastify = new Fastify()
|
|
128
|
+
|
|
129
|
+
const addressSchema = S.object()
|
|
130
|
+
.id('#address')
|
|
131
|
+
.prop('line1').required()
|
|
132
|
+
.prop('line2')
|
|
133
|
+
.prop('country').required()
|
|
134
|
+
.prop('city').required()
|
|
135
|
+
.prop('zipcode').required()
|
|
136
|
+
|
|
137
|
+
const commonSchemas = S.object()
|
|
138
|
+
.id('https://fastify/demo')
|
|
139
|
+
.definition('addressSchema', addressSchema)
|
|
140
|
+
|
|
141
|
+
fastify.addSchema(commonSchemas)
|
|
142
|
+
|
|
143
|
+
fastify.route({
|
|
144
|
+
method: 'POST',
|
|
145
|
+
url: '/query',
|
|
146
|
+
handler: () => {},
|
|
147
|
+
schema: {
|
|
148
|
+
query: S.object().prop('hello', S.string()).required(),
|
|
149
|
+
body: S.object().prop('hello', S.string()).required(),
|
|
150
|
+
params: S.object().prop('hello', S.string()).required(),
|
|
151
|
+
headers: S.object().prop('hello', S.string()).required(),
|
|
152
|
+
response: {
|
|
153
|
+
200: S.object().prop('hello', S.string()).required(),
|
|
154
|
+
201: S.object().prop('hello', S.string()).required()
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
fastify.route({
|
|
160
|
+
method: 'POST',
|
|
161
|
+
url: '/querystring',
|
|
162
|
+
handler: () => {},
|
|
163
|
+
schema: {
|
|
164
|
+
querystring: S.object().prop('hello', S.string()).required(),
|
|
165
|
+
body: S.object().prop('hello', S.string()).required(),
|
|
166
|
+
params: S.object().prop('hello', S.string()).required(),
|
|
167
|
+
headers: S.object().prop('hello', S.string()).required(),
|
|
168
|
+
response: {
|
|
169
|
+
200: S.object().prop('hello', S.string()).required(),
|
|
170
|
+
201: S.object().prop('hello', S.string()).required()
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
fastify.ready(t.error)
|
|
176
|
+
})
|
|
123
177
|
}
|
|
124
178
|
|
|
125
179
|
module.exports = fluentSchemaTest
|
package/test/hooks-async.js
CHANGED
|
@@ -4,7 +4,8 @@ const split = require('split2')
|
|
|
4
4
|
const sget = require('simple-get').concat
|
|
5
5
|
const Fastify = require('..')
|
|
6
6
|
const fs = require('fs')
|
|
7
|
-
const
|
|
7
|
+
const { promisify } = require('util')
|
|
8
|
+
const sleep = promisify(setTimeout)
|
|
8
9
|
|
|
9
10
|
function asyncHookTest (t) {
|
|
10
11
|
const test = t.test
|
|
@@ -231,6 +232,53 @@ function asyncHookTest (t) {
|
|
|
231
232
|
})
|
|
232
233
|
})
|
|
233
234
|
|
|
235
|
+
test('preValidation hooks should be able to block a request with async onSend', t => {
|
|
236
|
+
t.plan(5)
|
|
237
|
+
const fastify = Fastify()
|
|
238
|
+
|
|
239
|
+
fastify.addHook('preValidation', async (req, reply) => {
|
|
240
|
+
reply.send('hello')
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
fastify.addHook('onSend', async (req, reply, payload) => {
|
|
244
|
+
await sleep(10)
|
|
245
|
+
t.equal(payload, 'hello')
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
fastify.addHook('preHandler', async (request, reply) => {
|
|
249
|
+
t.fail('we should not be here')
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
fastify.addHook('onResponse', async (request, reply) => {
|
|
253
|
+
t.ok('called')
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
fastify.post('/', {
|
|
257
|
+
schema: {
|
|
258
|
+
body: {
|
|
259
|
+
type: 'object',
|
|
260
|
+
properties: {
|
|
261
|
+
hello: {
|
|
262
|
+
type: 'string'
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
required: ['hello']
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}, function (request, reply) {
|
|
269
|
+
t.fail('we should not be here')
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
fastify.inject({
|
|
273
|
+
url: '/',
|
|
274
|
+
method: 'POST'
|
|
275
|
+
}, (err, res) => {
|
|
276
|
+
t.error(err)
|
|
277
|
+
t.is(res.statusCode, 200)
|
|
278
|
+
t.is(res.payload, 'hello')
|
|
279
|
+
})
|
|
280
|
+
})
|
|
281
|
+
|
|
234
282
|
test('preSerialization hooks should be able to modify the payload', t => {
|
|
235
283
|
t.plan(3)
|
|
236
284
|
const fastify = Fastify()
|
|
@@ -339,6 +387,37 @@ function asyncHookTest (t) {
|
|
|
339
387
|
})
|
|
340
388
|
})
|
|
341
389
|
|
|
390
|
+
test('preHandler hooks should be able to block a request (last hook) with a delay in onSend', t => {
|
|
391
|
+
t.plan(5)
|
|
392
|
+
const fastify = Fastify()
|
|
393
|
+
|
|
394
|
+
fastify.addHook('preHandler', async (req, reply) => {
|
|
395
|
+
reply.send('hello')
|
|
396
|
+
})
|
|
397
|
+
|
|
398
|
+
fastify.addHook('onSend', async (req, reply, payload) => {
|
|
399
|
+
await sleep(10)
|
|
400
|
+
t.equal(payload, 'hello')
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
fastify.addHook('onResponse', async (request, reply) => {
|
|
404
|
+
t.ok('called')
|
|
405
|
+
})
|
|
406
|
+
|
|
407
|
+
fastify.get('/', function (request, reply) {
|
|
408
|
+
t.fail('we should not be here')
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
fastify.inject({
|
|
412
|
+
url: '/',
|
|
413
|
+
method: 'GET'
|
|
414
|
+
}, (err, res) => {
|
|
415
|
+
t.error(err)
|
|
416
|
+
t.is(res.statusCode, 200)
|
|
417
|
+
t.is(res.payload, 'hello')
|
|
418
|
+
})
|
|
419
|
+
})
|
|
420
|
+
|
|
342
421
|
test('onRequest respond with a stream', t => {
|
|
343
422
|
t.plan(4)
|
|
344
423
|
const fastify = Fastify()
|
package/test/hooks.test.js
CHANGED
|
@@ -1935,7 +1935,7 @@ test('request in onRequest, preParsing, preValidation and onResponse', t => {
|
|
|
1935
1935
|
t.deepEqual(request.headers, {
|
|
1936
1936
|
'content-length': '17',
|
|
1937
1937
|
'content-type': 'application/json',
|
|
1938
|
-
|
|
1938
|
+
host: 'localhost:80',
|
|
1939
1939
|
'user-agent': 'lightMyRequest',
|
|
1940
1940
|
'x-custom': 'hello'
|
|
1941
1941
|
})
|
|
@@ -1949,7 +1949,7 @@ test('request in onRequest, preParsing, preValidation and onResponse', t => {
|
|
|
1949
1949
|
t.deepEqual(request.headers, {
|
|
1950
1950
|
'content-length': '17',
|
|
1951
1951
|
'content-type': 'application/json',
|
|
1952
|
-
|
|
1952
|
+
host: 'localhost:80',
|
|
1953
1953
|
'user-agent': 'lightMyRequest',
|
|
1954
1954
|
'x-custom': 'hello'
|
|
1955
1955
|
})
|
|
@@ -1963,7 +1963,7 @@ test('request in onRequest, preParsing, preValidation and onResponse', t => {
|
|
|
1963
1963
|
t.deepEqual(request.headers, {
|
|
1964
1964
|
'content-length': '17',
|
|
1965
1965
|
'content-type': 'application/json',
|
|
1966
|
-
|
|
1966
|
+
host: 'localhost:80',
|
|
1967
1967
|
'user-agent': 'lightMyRequest',
|
|
1968
1968
|
'x-custom': 'hello'
|
|
1969
1969
|
})
|
|
@@ -1977,7 +1977,7 @@ test('request in onRequest, preParsing, preValidation and onResponse', t => {
|
|
|
1977
1977
|
t.deepEqual(request.headers, {
|
|
1978
1978
|
'content-length': '17',
|
|
1979
1979
|
'content-type': 'application/json',
|
|
1980
|
-
|
|
1980
|
+
host: 'localhost:80',
|
|
1981
1981
|
'user-agent': 'lightMyRequest',
|
|
1982
1982
|
'x-custom': 'hello'
|
|
1983
1983
|
})
|
package/test/http2/closing.js
CHANGED
|
@@ -1,48 +1,101 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const t = require('tap')
|
|
4
|
-
const test = t.test
|
|
5
4
|
const Fastify = require('../..')
|
|
6
5
|
const http2 = require('http2')
|
|
7
6
|
const semver = require('semver')
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
8
|
+
t.test('http/2 request while fastify closing', t => {
|
|
9
|
+
let fastify
|
|
10
|
+
try {
|
|
11
|
+
fastify = Fastify({
|
|
12
|
+
http2: true
|
|
13
|
+
})
|
|
14
|
+
t.pass('http2 successfully loaded')
|
|
15
|
+
} catch (e) {
|
|
16
|
+
t.fail('http2 loading failed', e)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
fastify.get('/', () => Promise.resolve({}))
|
|
20
|
+
|
|
21
|
+
fastify.listen(0, err => {
|
|
22
|
+
t.error(err)
|
|
23
|
+
fastify.server.unref()
|
|
24
|
+
|
|
25
|
+
// Skipped because there is likely a bug on Node 8.
|
|
26
|
+
t.test('return 200', { skip: semver.lt(process.versions.node, '10.15.0') }, t => {
|
|
27
|
+
const url = `http://127.0.0.1:${fastify.server.address().port}`
|
|
28
|
+
const session = http2.connect(url, function () {
|
|
29
|
+
this.request({
|
|
30
|
+
':method': 'GET',
|
|
31
|
+
':path': '/'
|
|
32
|
+
}).on('response', headers => {
|
|
33
|
+
t.strictEqual(headers[':status'], 503)
|
|
34
|
+
t.end()
|
|
35
|
+
this.destroy()
|
|
36
|
+
}).on('error', () => {
|
|
37
|
+
// Nothing to do here,
|
|
38
|
+
// we are not interested in this error that might
|
|
39
|
+
// happen or not
|
|
40
|
+
})
|
|
41
|
+
fastify.close()
|
|
42
|
+
})
|
|
43
|
+
session.on('error', () => {
|
|
35
44
|
// Nothing to do here,
|
|
36
45
|
// we are not interested in this error that might
|
|
37
46
|
// happen or not
|
|
47
|
+
t.end()
|
|
38
48
|
})
|
|
39
|
-
fastify.close()
|
|
40
49
|
})
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
|
|
51
|
+
t.end()
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
t.test('http/2 request while fastify closing - return503OnClosing: false', t => {
|
|
56
|
+
let fastify
|
|
57
|
+
try {
|
|
58
|
+
fastify = Fastify({
|
|
59
|
+
http2: true,
|
|
60
|
+
return503OnClosing: false
|
|
46
61
|
})
|
|
62
|
+
t.pass('http2 successfully loaded')
|
|
63
|
+
} catch (e) {
|
|
64
|
+
t.fail('http2 loading failed', e)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
fastify.get('/', () => Promise.resolve({}))
|
|
68
|
+
|
|
69
|
+
fastify.listen(0, err => {
|
|
70
|
+
t.error(err)
|
|
71
|
+
fastify.server.unref()
|
|
72
|
+
|
|
73
|
+
// Skipped because there is likely a bug on Node 8.
|
|
74
|
+
t.test('return 200', { skip: semver.lt(process.versions.node, '10.15.0') }, t => {
|
|
75
|
+
const url = `http://127.0.0.1:${fastify.server.address().port}`
|
|
76
|
+
const session = http2.connect(url, function () {
|
|
77
|
+
this.request({
|
|
78
|
+
':method': 'GET',
|
|
79
|
+
':path': '/'
|
|
80
|
+
}).on('response', headers => {
|
|
81
|
+
t.strictEqual(headers[':status'], 200)
|
|
82
|
+
t.end()
|
|
83
|
+
this.destroy()
|
|
84
|
+
}).on('error', () => {
|
|
85
|
+
// Nothing to do here,
|
|
86
|
+
// we are not interested in this error that might
|
|
87
|
+
// happen or not
|
|
88
|
+
})
|
|
89
|
+
fastify.close()
|
|
90
|
+
})
|
|
91
|
+
session.on('error', () => {
|
|
92
|
+
// Nothing to do here,
|
|
93
|
+
// we are not interested in this error that might
|
|
94
|
+
// happen or not
|
|
95
|
+
t.end()
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
t.end()
|
|
47
100
|
})
|
|
48
101
|
})
|
|
@@ -14,7 +14,7 @@ const {
|
|
|
14
14
|
} = require('../../lib/symbols')
|
|
15
15
|
|
|
16
16
|
test('Once called, Reply should return an object with methods', t => {
|
|
17
|
-
t.plan(
|
|
17
|
+
t.plan(13)
|
|
18
18
|
const response = { res: 'res' }
|
|
19
19
|
function context () {}
|
|
20
20
|
function request () {}
|
|
@@ -27,6 +27,7 @@ test('Once called, Reply should return an object with methods', t => {
|
|
|
27
27
|
t.is(typeof reply.status, 'function')
|
|
28
28
|
t.is(typeof reply.header, 'function')
|
|
29
29
|
t.is(typeof reply.serialize, 'function')
|
|
30
|
+
t.is(typeof reply.getResponseTime, 'function')
|
|
30
31
|
t.is(typeof reply[kReplyHeaders], 'object')
|
|
31
32
|
t.strictEqual(reply.res, response)
|
|
32
33
|
t.strictEqual(reply.context, context)
|
|
@@ -977,3 +978,277 @@ test('should throw error when attempting to set reply.sent more than once', t =>
|
|
|
977
978
|
t.pass()
|
|
978
979
|
})
|
|
979
980
|
})
|
|
981
|
+
|
|
982
|
+
test('reply.getResponseTime() should return 0 before the timer is initialised on the reply by setting up response listeners', t => {
|
|
983
|
+
t.plan(1)
|
|
984
|
+
const response = { statusCode: 200 }
|
|
985
|
+
const context = {}
|
|
986
|
+
const reply = new Reply(response, context, null)
|
|
987
|
+
t.equal(reply.getResponseTime(), 0)
|
|
988
|
+
})
|
|
989
|
+
|
|
990
|
+
test('reply.getResponseTime() should return a number greater than 0 after the timer is initialised on the reply by setting up response listeners', t => {
|
|
991
|
+
t.plan(1)
|
|
992
|
+
const fastify = require('../..')()
|
|
993
|
+
fastify.route({
|
|
994
|
+
method: 'GET',
|
|
995
|
+
url: '/',
|
|
996
|
+
handler: (req, reply) => {
|
|
997
|
+
reply.send('hello world')
|
|
998
|
+
}
|
|
999
|
+
})
|
|
1000
|
+
|
|
1001
|
+
fastify.addHook('onResponse', (req, reply) => {
|
|
1002
|
+
t.true(reply.getResponseTime() > 0)
|
|
1003
|
+
t.end()
|
|
1004
|
+
})
|
|
1005
|
+
|
|
1006
|
+
fastify.inject({ method: 'GET', url: '/' })
|
|
1007
|
+
})
|
|
1008
|
+
|
|
1009
|
+
test('reply should use the custom serializer', t => {
|
|
1010
|
+
t.plan(4)
|
|
1011
|
+
const fastify = require('../..')()
|
|
1012
|
+
fastify.setReplySerializer((payload, statusCode) => {
|
|
1013
|
+
t.deepEqual(payload, { foo: 'bar' })
|
|
1014
|
+
t.equal(statusCode, 200)
|
|
1015
|
+
payload.foo = 'bar bar'
|
|
1016
|
+
return JSON.stringify(payload)
|
|
1017
|
+
})
|
|
1018
|
+
|
|
1019
|
+
fastify.route({
|
|
1020
|
+
method: 'GET',
|
|
1021
|
+
url: '/',
|
|
1022
|
+
handler: (req, reply) => {
|
|
1023
|
+
reply.send({ foo: 'bar' })
|
|
1024
|
+
}
|
|
1025
|
+
})
|
|
1026
|
+
|
|
1027
|
+
fastify.inject({
|
|
1028
|
+
method: 'GET',
|
|
1029
|
+
url: '/'
|
|
1030
|
+
}, (err, res) => {
|
|
1031
|
+
t.error(err)
|
|
1032
|
+
t.strictEqual(res.payload, '{"foo":"bar bar"}')
|
|
1033
|
+
})
|
|
1034
|
+
})
|
|
1035
|
+
|
|
1036
|
+
test('reply should use the right serializer in encapsulated context', t => {
|
|
1037
|
+
t.plan(9)
|
|
1038
|
+
|
|
1039
|
+
const fastify = require('../..')()
|
|
1040
|
+
fastify.setReplySerializer((payload) => {
|
|
1041
|
+
t.deepEqual(payload, { foo: 'bar' })
|
|
1042
|
+
payload.foo = 'bar bar'
|
|
1043
|
+
return JSON.stringify(payload)
|
|
1044
|
+
})
|
|
1045
|
+
|
|
1046
|
+
fastify.route({
|
|
1047
|
+
method: 'GET',
|
|
1048
|
+
url: '/',
|
|
1049
|
+
handler: (req, reply) => { reply.send({ foo: 'bar' }) }
|
|
1050
|
+
})
|
|
1051
|
+
|
|
1052
|
+
fastify.register(function (instance, opts, next) {
|
|
1053
|
+
instance.route({
|
|
1054
|
+
method: 'GET',
|
|
1055
|
+
url: '/sub',
|
|
1056
|
+
handler: (req, reply) => { reply.send({ john: 'doo' }) }
|
|
1057
|
+
})
|
|
1058
|
+
instance.setReplySerializer((payload) => {
|
|
1059
|
+
t.deepEqual(payload, { john: 'doo' })
|
|
1060
|
+
payload.john = 'too too'
|
|
1061
|
+
return JSON.stringify(payload)
|
|
1062
|
+
})
|
|
1063
|
+
next()
|
|
1064
|
+
})
|
|
1065
|
+
|
|
1066
|
+
fastify.register(function (instance, opts, next) {
|
|
1067
|
+
instance.route({
|
|
1068
|
+
method: 'GET',
|
|
1069
|
+
url: '/sub',
|
|
1070
|
+
handler: (req, reply) => { reply.send({ sweet: 'potato' }) }
|
|
1071
|
+
})
|
|
1072
|
+
instance.setReplySerializer((payload) => {
|
|
1073
|
+
t.deepEqual(payload, { sweet: 'potato' })
|
|
1074
|
+
payload.sweet = 'potato potato'
|
|
1075
|
+
return JSON.stringify(payload)
|
|
1076
|
+
})
|
|
1077
|
+
next()
|
|
1078
|
+
}, { prefix: 'sub' })
|
|
1079
|
+
|
|
1080
|
+
fastify.inject({
|
|
1081
|
+
method: 'GET',
|
|
1082
|
+
url: '/'
|
|
1083
|
+
}, (err, res) => {
|
|
1084
|
+
t.error(err)
|
|
1085
|
+
t.strictEqual(res.payload, '{"foo":"bar bar"}')
|
|
1086
|
+
})
|
|
1087
|
+
|
|
1088
|
+
fastify.inject({
|
|
1089
|
+
method: 'GET',
|
|
1090
|
+
url: '/sub'
|
|
1091
|
+
}, (err, res) => {
|
|
1092
|
+
t.error(err)
|
|
1093
|
+
t.strictEqual(res.payload, '{"john":"too too"}')
|
|
1094
|
+
})
|
|
1095
|
+
|
|
1096
|
+
fastify.inject({
|
|
1097
|
+
method: 'GET',
|
|
1098
|
+
url: '/sub/sub'
|
|
1099
|
+
}, (err, res) => {
|
|
1100
|
+
t.error(err)
|
|
1101
|
+
t.strictEqual(res.payload, '{"sweet":"potato potato"}')
|
|
1102
|
+
})
|
|
1103
|
+
})
|
|
1104
|
+
|
|
1105
|
+
test('reply should use the right serializer in deep encapsulated context', t => {
|
|
1106
|
+
t.plan(8)
|
|
1107
|
+
|
|
1108
|
+
const fastify = require('../..')()
|
|
1109
|
+
|
|
1110
|
+
fastify.route({
|
|
1111
|
+
method: 'GET',
|
|
1112
|
+
url: '/',
|
|
1113
|
+
handler: (req, reply) => { reply.send({ foo: 'bar' }) }
|
|
1114
|
+
})
|
|
1115
|
+
|
|
1116
|
+
fastify.register(function (instance, opts, next) {
|
|
1117
|
+
instance.route({
|
|
1118
|
+
method: 'GET',
|
|
1119
|
+
url: '/sub',
|
|
1120
|
+
handler: (req, reply) => { reply.send({ john: 'doo' }) }
|
|
1121
|
+
})
|
|
1122
|
+
instance.setReplySerializer((payload) => {
|
|
1123
|
+
t.deepEqual(payload, { john: 'doo' })
|
|
1124
|
+
payload.john = 'too too'
|
|
1125
|
+
return JSON.stringify(payload)
|
|
1126
|
+
})
|
|
1127
|
+
|
|
1128
|
+
instance.register(function (subInstance, opts, next) {
|
|
1129
|
+
subInstance.route({
|
|
1130
|
+
method: 'GET',
|
|
1131
|
+
url: '/deep',
|
|
1132
|
+
handler: (req, reply) => { reply.send({ john: 'deep' }) }
|
|
1133
|
+
})
|
|
1134
|
+
subInstance.setReplySerializer((payload) => {
|
|
1135
|
+
t.deepEqual(payload, { john: 'deep' })
|
|
1136
|
+
payload.john = 'deep deep'
|
|
1137
|
+
return JSON.stringify(payload)
|
|
1138
|
+
})
|
|
1139
|
+
next()
|
|
1140
|
+
})
|
|
1141
|
+
next()
|
|
1142
|
+
})
|
|
1143
|
+
|
|
1144
|
+
fastify.inject({
|
|
1145
|
+
method: 'GET',
|
|
1146
|
+
url: '/'
|
|
1147
|
+
}, (err, res) => {
|
|
1148
|
+
t.error(err)
|
|
1149
|
+
t.strictEqual(res.payload, '{"foo":"bar"}')
|
|
1150
|
+
})
|
|
1151
|
+
|
|
1152
|
+
fastify.inject({
|
|
1153
|
+
method: 'GET',
|
|
1154
|
+
url: '/sub'
|
|
1155
|
+
}, (err, res) => {
|
|
1156
|
+
t.error(err)
|
|
1157
|
+
t.strictEqual(res.payload, '{"john":"too too"}')
|
|
1158
|
+
})
|
|
1159
|
+
|
|
1160
|
+
fastify.inject({
|
|
1161
|
+
method: 'GET',
|
|
1162
|
+
url: '/deep'
|
|
1163
|
+
}, (err, res) => {
|
|
1164
|
+
t.error(err)
|
|
1165
|
+
t.strictEqual(res.payload, '{"john":"deep deep"}')
|
|
1166
|
+
})
|
|
1167
|
+
})
|
|
1168
|
+
|
|
1169
|
+
test('reply should use the route serializer', t => {
|
|
1170
|
+
t.plan(3)
|
|
1171
|
+
|
|
1172
|
+
const fastify = require('../..')()
|
|
1173
|
+
fastify.setReplySerializer(() => {
|
|
1174
|
+
t.fail('this serializer should not be executed')
|
|
1175
|
+
})
|
|
1176
|
+
|
|
1177
|
+
fastify.route({
|
|
1178
|
+
method: 'GET',
|
|
1179
|
+
url: '/',
|
|
1180
|
+
handler: (req, reply) => {
|
|
1181
|
+
reply
|
|
1182
|
+
.serializer((payload) => {
|
|
1183
|
+
t.deepEqual(payload, { john: 'doo' })
|
|
1184
|
+
payload.john = 'too too'
|
|
1185
|
+
return JSON.stringify(payload)
|
|
1186
|
+
})
|
|
1187
|
+
.send({ john: 'doo' })
|
|
1188
|
+
}
|
|
1189
|
+
})
|
|
1190
|
+
|
|
1191
|
+
fastify.inject({
|
|
1192
|
+
method: 'GET',
|
|
1193
|
+
url: '/'
|
|
1194
|
+
}, (err, res) => {
|
|
1195
|
+
t.error(err)
|
|
1196
|
+
t.strictEqual(res.payload, '{"john":"too too"}')
|
|
1197
|
+
})
|
|
1198
|
+
})
|
|
1199
|
+
|
|
1200
|
+
test('cannot set the replySerializer when the server is running', t => {
|
|
1201
|
+
t.plan(2)
|
|
1202
|
+
|
|
1203
|
+
const fastify = require('../..')()
|
|
1204
|
+
t.teardown(fastify.close.bind(fastify))
|
|
1205
|
+
|
|
1206
|
+
fastify.listen(err => {
|
|
1207
|
+
t.error(err)
|
|
1208
|
+
try {
|
|
1209
|
+
fastify.setReplySerializer(() => {})
|
|
1210
|
+
t.fail('this serializer should not be setup')
|
|
1211
|
+
} catch (e) {
|
|
1212
|
+
t.is(e.message, 'Cannot call "setReplySerializer" when fastify instance is already started!')
|
|
1213
|
+
}
|
|
1214
|
+
})
|
|
1215
|
+
})
|
|
1216
|
+
|
|
1217
|
+
test('reply should not call the custom serializer for errors and not found', t => {
|
|
1218
|
+
t.plan(9)
|
|
1219
|
+
|
|
1220
|
+
const fastify = require('../..')()
|
|
1221
|
+
fastify.setReplySerializer((payload, statusCode) => {
|
|
1222
|
+
t.deepEqual(payload, { foo: 'bar' })
|
|
1223
|
+
t.equal(statusCode, 200)
|
|
1224
|
+
return JSON.stringify(payload)
|
|
1225
|
+
})
|
|
1226
|
+
|
|
1227
|
+
fastify.get('/', (req, reply) => { reply.send({ foo: 'bar' }) })
|
|
1228
|
+
fastify.get('/err', (req, reply) => { reply.send(new Error('an error')) })
|
|
1229
|
+
|
|
1230
|
+
fastify.inject({
|
|
1231
|
+
method: 'GET',
|
|
1232
|
+
url: '/'
|
|
1233
|
+
}, (err, res) => {
|
|
1234
|
+
t.error(err)
|
|
1235
|
+
t.strictEqual(res.statusCode, 200)
|
|
1236
|
+
t.strictEqual(res.payload, '{"foo":"bar"}')
|
|
1237
|
+
})
|
|
1238
|
+
|
|
1239
|
+
fastify.inject({
|
|
1240
|
+
method: 'GET',
|
|
1241
|
+
url: '/err'
|
|
1242
|
+
}, (err, res) => {
|
|
1243
|
+
t.error(err)
|
|
1244
|
+
t.strictEqual(res.statusCode, 500)
|
|
1245
|
+
})
|
|
1246
|
+
|
|
1247
|
+
fastify.inject({
|
|
1248
|
+
method: 'GET',
|
|
1249
|
+
url: '/not-existing'
|
|
1250
|
+
}, (err, res) => {
|
|
1251
|
+
t.error(err)
|
|
1252
|
+
t.strictEqual(res.statusCode, 404)
|
|
1253
|
+
})
|
|
1254
|
+
})
|