1 | 'use strict'
|
2 |
|
3 | const t = require('tap')
|
4 | const test = t.test
|
5 | const semver = require('semver')
|
6 | const sget = require('simple-get').concat
|
7 | const stream = require('stream')
|
8 | const Fastify = require('..')
|
9 | const fp = require('fastify-plugin')
|
10 | const fs = require('fs')
|
11 | const split = require('split2')
|
12 | const symbols = require('../lib/symbols.js')
|
13 |
|
14 | const payload = { hello: 'world' }
|
15 |
|
16 | test('hooks', t => {
|
17 | t.plan(37)
|
18 | const fastify = Fastify()
|
19 |
|
20 | try {
|
21 | fastify.addHook('preHandler', function (request, reply, next) {
|
22 | t.is(request.test, 'the request is coming')
|
23 | t.is(reply.test, 'the reply has come')
|
24 | if (request.raw.method === 'HEAD') {
|
25 | next(new Error('some error'))
|
26 | } else {
|
27 | next()
|
28 | }
|
29 | })
|
30 | t.pass()
|
31 | } catch (e) {
|
32 | t.fail()
|
33 | }
|
34 |
|
35 | try {
|
36 | fastify.addHook('preParsing', function (request, reply, next) {
|
37 | request.preParsing = true
|
38 | t.is(request.test, 'the request is coming')
|
39 | t.is(reply.test, 'the reply has come')
|
40 | next()
|
41 | })
|
42 | t.pass()
|
43 | } catch (e) {
|
44 | t.fail()
|
45 | }
|
46 |
|
47 | try {
|
48 | fastify.addHook('preValidation', function (request, reply, next) {
|
49 | t.is(request.preParsing, true)
|
50 | t.is(request.test, 'the request is coming')
|
51 | t.is(reply.test, 'the reply has come')
|
52 | next()
|
53 | })
|
54 | t.pass()
|
55 | } catch (e) {
|
56 | t.fail()
|
57 | }
|
58 |
|
59 | try {
|
60 | fastify.addHook('preSerialization', function (request, reply, payload, next) {
|
61 | t.ok('preSerialization called')
|
62 | next()
|
63 | })
|
64 | t.pass()
|
65 | } catch (e) {
|
66 | t.fail()
|
67 | }
|
68 |
|
69 | try {
|
70 | fastify.addHook('onRequest', function (request, reply, next) {
|
71 | request.test = 'the request is coming'
|
72 | reply.test = 'the reply has come'
|
73 | if (request.raw.method === 'DELETE') {
|
74 | next(new Error('some error'))
|
75 | } else {
|
76 | next()
|
77 | }
|
78 | })
|
79 | t.pass()
|
80 | } catch (e) {
|
81 | t.fail()
|
82 | }
|
83 |
|
84 | fastify.addHook('onResponse', function (request, reply, next) {
|
85 | t.ok('onResponse called')
|
86 | next()
|
87 | })
|
88 |
|
89 | fastify.addHook('onSend', function (req, reply, thePayload, next) {
|
90 | t.ok('onSend called')
|
91 | next()
|
92 | })
|
93 |
|
94 | fastify.route({
|
95 | method: 'GET',
|
96 | url: '/',
|
97 | handler: function (req, reply) {
|
98 | t.is(req.test, 'the request is coming')
|
99 | t.is(reply.test, 'the reply has come')
|
100 | reply.code(200).send(payload)
|
101 | },
|
102 | response: {
|
103 | 200: {
|
104 | type: 'object'
|
105 | }
|
106 | }
|
107 | })
|
108 |
|
109 | fastify.head('/', function (req, reply) {
|
110 | reply.code(200).send(payload)
|
111 | })
|
112 |
|
113 | fastify.delete('/', function (req, reply) {
|
114 | reply.code(200).send(payload)
|
115 | })
|
116 |
|
117 | fastify.listen(0, err => {
|
118 | t.error(err)
|
119 | fastify.server.unref()
|
120 |
|
121 | sget({
|
122 | method: 'GET',
|
123 | url: 'http://localhost:' + fastify.server.address().port
|
124 | }, (err, response, body) => {
|
125 | t.error(err)
|
126 | t.strictEqual(response.statusCode, 200)
|
127 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
128 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
129 | })
|
130 |
|
131 | sget({
|
132 | method: 'HEAD',
|
133 | url: 'http://localhost:' + fastify.server.address().port
|
134 | }, (err, response, body) => {
|
135 | t.error(err)
|
136 | t.strictEqual(response.statusCode, 500)
|
137 | })
|
138 |
|
139 | sget({
|
140 | method: 'DELETE',
|
141 | url: 'http://localhost:' + fastify.server.address().port
|
142 | }, (err, response, body) => {
|
143 | t.error(err)
|
144 | t.strictEqual(response.statusCode, 500)
|
145 | })
|
146 | })
|
147 | })
|
148 |
|
149 | test('onRequest hook should support encapsulation / 1', t => {
|
150 | t.plan(5)
|
151 | const fastify = Fastify()
|
152 |
|
153 | fastify.register((instance, opts, next) => {
|
154 | instance.addHook('onRequest', (req, reply, next) => {
|
155 | t.strictEqual(req.raw.url, '/plugin')
|
156 | next()
|
157 | })
|
158 |
|
159 | instance.get('/plugin', (request, reply) => {
|
160 | reply.send()
|
161 | })
|
162 |
|
163 | next()
|
164 | })
|
165 |
|
166 | fastify.get('/root', (request, reply) => {
|
167 | reply.send()
|
168 | })
|
169 |
|
170 | fastify.inject('/root', (err, res) => {
|
171 | t.error(err)
|
172 | t.strictEqual(res.statusCode, 200)
|
173 | })
|
174 |
|
175 | fastify.inject('/plugin', (err, res) => {
|
176 | t.error(err)
|
177 | t.strictEqual(res.statusCode, 200)
|
178 | })
|
179 | })
|
180 |
|
181 | test('onRequest hook should support encapsulation / 2', t => {
|
182 | t.plan(3)
|
183 | const fastify = Fastify()
|
184 | var pluginInstance
|
185 |
|
186 | fastify.addHook('onRequest', () => {})
|
187 |
|
188 | fastify.register((instance, opts, next) => {
|
189 | instance.addHook('onRequest', () => {})
|
190 | pluginInstance = instance
|
191 | next()
|
192 | })
|
193 |
|
194 | fastify.ready(err => {
|
195 | t.error(err)
|
196 | t.is(fastify[symbols.kHooks].onRequest.length, 1)
|
197 | t.is(pluginInstance[symbols.kHooks].onRequest.length, 2)
|
198 | })
|
199 | })
|
200 |
|
201 | test('onRequest hook should support encapsulation / 3', t => {
|
202 | t.plan(20)
|
203 | const fastify = Fastify()
|
204 | fastify.decorate('hello', 'world')
|
205 |
|
206 | fastify.addHook('onRequest', function (req, reply, next) {
|
207 | t.ok(this.hello)
|
208 | t.ok(this.hello2)
|
209 | req.first = true
|
210 | next()
|
211 | })
|
212 |
|
213 | fastify.decorate('hello2', 'world')
|
214 |
|
215 | fastify.get('/first', (req, reply) => {
|
216 | t.ok(req.first)
|
217 | t.notOk(req.second)
|
218 | reply.send({ hello: 'world' })
|
219 | })
|
220 |
|
221 | fastify.register((instance, opts, next) => {
|
222 | instance.decorate('hello3', 'world')
|
223 | instance.addHook('onRequest', function (req, reply, next) {
|
224 | t.ok(this.hello)
|
225 | t.ok(this.hello2)
|
226 | t.ok(this.hello3)
|
227 | req.second = true
|
228 | next()
|
229 | })
|
230 |
|
231 | instance.get('/second', (req, reply) => {
|
232 | t.ok(req.first)
|
233 | t.ok(req.second)
|
234 | reply.send({ hello: 'world' })
|
235 | })
|
236 |
|
237 | next()
|
238 | })
|
239 |
|
240 | fastify.listen(0, err => {
|
241 | t.error(err)
|
242 | fastify.server.unref()
|
243 |
|
244 | sget({
|
245 | method: 'GET',
|
246 | url: 'http://localhost:' + fastify.server.address().port + '/first'
|
247 | }, (err, response, body) => {
|
248 | t.error(err)
|
249 | t.strictEqual(response.statusCode, 200)
|
250 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
251 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
252 | })
|
253 |
|
254 | sget({
|
255 | method: 'GET',
|
256 | url: 'http://localhost:' + fastify.server.address().port + '/second'
|
257 | }, (err, response, body) => {
|
258 | t.error(err)
|
259 | t.strictEqual(response.statusCode, 200)
|
260 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
261 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
262 | })
|
263 | })
|
264 | })
|
265 |
|
266 | test('preHandler hook should support encapsulation / 5', t => {
|
267 | t.plan(17)
|
268 | const fastify = Fastify()
|
269 | fastify.decorate('hello', 'world')
|
270 |
|
271 | fastify.addHook('preHandler', function (req, res, next) {
|
272 | t.ok(this.hello)
|
273 | req.first = true
|
274 | next()
|
275 | })
|
276 |
|
277 | fastify.get('/first', (req, reply) => {
|
278 | t.ok(req.first)
|
279 | t.notOk(req.second)
|
280 | reply.send({ hello: 'world' })
|
281 | })
|
282 |
|
283 | fastify.register((instance, opts, next) => {
|
284 | instance.decorate('hello2', 'world')
|
285 | instance.addHook('preHandler', function (req, res, next) {
|
286 | t.ok(this.hello)
|
287 | t.ok(this.hello2)
|
288 | req.second = true
|
289 | next()
|
290 | })
|
291 |
|
292 | instance.get('/second', (req, reply) => {
|
293 | t.ok(req.first)
|
294 | t.ok(req.second)
|
295 | reply.send({ hello: 'world' })
|
296 | })
|
297 |
|
298 | next()
|
299 | })
|
300 |
|
301 | fastify.listen(0, err => {
|
302 | t.error(err)
|
303 | fastify.server.unref()
|
304 |
|
305 | sget({
|
306 | method: 'GET',
|
307 | url: 'http://localhost:' + fastify.server.address().port + '/first'
|
308 | }, (err, response, body) => {
|
309 | t.error(err)
|
310 | t.strictEqual(response.statusCode, 200)
|
311 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
312 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
313 | })
|
314 |
|
315 | sget({
|
316 | method: 'GET',
|
317 | url: 'http://localhost:' + fastify.server.address().port + '/second'
|
318 | }, (err, response, body) => {
|
319 | t.error(err)
|
320 | t.strictEqual(response.statusCode, 200)
|
321 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
322 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
323 | })
|
324 | })
|
325 | })
|
326 |
|
327 | test('onRoute hook should be called / 1', t => {
|
328 | t.plan(2)
|
329 | const fastify = Fastify()
|
330 |
|
331 | fastify.register((instance, opts, next) => {
|
332 | instance.addHook('onRoute', () => {
|
333 | t.pass()
|
334 | })
|
335 | instance.get('/', opts, function (req, reply) {
|
336 | reply.send()
|
337 | })
|
338 | next()
|
339 | })
|
340 |
|
341 | fastify.ready(err => {
|
342 | t.error(err)
|
343 | })
|
344 | })
|
345 |
|
346 | test('onRoute hook should be called / 2', t => {
|
347 | t.plan(5)
|
348 | let firstHandler = 0
|
349 | let secondHandler = 0
|
350 | const fastify = Fastify()
|
351 | fastify.addHook('onRoute', (route) => {
|
352 | t.pass()
|
353 | firstHandler++
|
354 | })
|
355 |
|
356 | fastify.register((instance, opts, next) => {
|
357 | instance.addHook('onRoute', (route) => {
|
358 | t.pass()
|
359 | secondHandler++
|
360 | })
|
361 | instance.get('/', opts, function (req, reply) {
|
362 | reply.send()
|
363 | })
|
364 | next()
|
365 | })
|
366 | .after(() => {
|
367 | t.strictEqual(firstHandler, 1)
|
368 | t.strictEqual(secondHandler, 1)
|
369 | })
|
370 |
|
371 | fastify.ready(err => {
|
372 | t.error(err)
|
373 | })
|
374 | })
|
375 |
|
376 | test('onRoute hook should be called / 3', t => {
|
377 | t.plan(6)
|
378 | const fastify = Fastify()
|
379 |
|
380 | function handler (req, reply) {
|
381 | reply.send()
|
382 | }
|
383 |
|
384 | fastify.addHook('onRoute', (route) => {
|
385 | t.pass()
|
386 | })
|
387 |
|
388 | fastify.register((instance, opts, next) => {
|
389 | instance.addHook('onRoute', (route) => {
|
390 | t.pass()
|
391 | })
|
392 | instance.get('/a', handler)
|
393 | next()
|
394 | })
|
395 | .after((err, done) => {
|
396 | t.error(err)
|
397 | setTimeout(() => {
|
398 | fastify.get('/b', handler)
|
399 | done()
|
400 | }, 10)
|
401 | })
|
402 |
|
403 | fastify.ready(err => {
|
404 | t.error(err)
|
405 | })
|
406 | })
|
407 |
|
408 | test('onRoute should keep the context', t => {
|
409 | t.plan(4)
|
410 | const fastify = Fastify()
|
411 | fastify.register((instance, opts, next) => {
|
412 | instance.decorate('test', true)
|
413 | instance.addHook('onRoute', onRoute)
|
414 | t.ok(instance.prototype === fastify.prototype)
|
415 |
|
416 | function onRoute (route) {
|
417 | t.ok(this.test)
|
418 | t.strictEqual(this, instance)
|
419 | }
|
420 |
|
421 | instance.get('/', opts, function (req, reply) {
|
422 | reply.send()
|
423 | })
|
424 |
|
425 | next()
|
426 | })
|
427 |
|
428 | fastify.close((err) => {
|
429 | t.error(err)
|
430 | })
|
431 | })
|
432 |
|
433 | test('onRoute hook should pass correct route', t => {
|
434 | t.plan(7)
|
435 | const fastify = Fastify()
|
436 | fastify.addHook('onRoute', (route) => {
|
437 | t.strictEqual(route.method, 'GET')
|
438 | t.strictEqual(route.url, '/')
|
439 | t.strictEqual(route.path, '/')
|
440 | })
|
441 |
|
442 | fastify.register((instance, opts, next) => {
|
443 | instance.addHook('onRoute', (route) => {
|
444 | t.strictEqual(route.method, 'GET')
|
445 | t.strictEqual(route.url, '/')
|
446 | t.strictEqual(route.path, '/')
|
447 | })
|
448 | instance.get('/', opts, function (req, reply) {
|
449 | reply.send()
|
450 | })
|
451 | next()
|
452 | })
|
453 |
|
454 | fastify.ready(err => {
|
455 | t.error(err)
|
456 | })
|
457 | })
|
458 |
|
459 | test('onRoute hook should pass correct route with custom prefix', t => {
|
460 | t.plan(9)
|
461 | const fastify = Fastify()
|
462 | fastify.addHook('onRoute', function (route) {
|
463 | t.strictEqual(route.method, 'GET')
|
464 | t.strictEqual(route.url, '/v1/foo')
|
465 | t.strictEqual(route.path, '/v1/foo')
|
466 | t.strictEqual(route.prefix, '/v1')
|
467 | })
|
468 |
|
469 | fastify.register((instance, opts, next) => {
|
470 | instance.addHook('onRoute', function (route) {
|
471 | t.strictEqual(route.method, 'GET')
|
472 | t.strictEqual(route.url, '/v1/foo')
|
473 | t.strictEqual(route.path, '/v1/foo')
|
474 | t.strictEqual(route.prefix, '/v1')
|
475 | })
|
476 | instance.get('/foo', opts, function (req, reply) {
|
477 | reply.send()
|
478 | })
|
479 | next()
|
480 | }, { prefix: '/v1' })
|
481 |
|
482 | fastify.ready(err => {
|
483 | t.error(err)
|
484 | })
|
485 | })
|
486 |
|
487 | test('onRoute hook should pass correct route with custom options', t => {
|
488 | t.plan(5)
|
489 | const fastify = Fastify()
|
490 | fastify.register((instance, opts, next) => {
|
491 | instance.addHook('onRoute', function (route) {
|
492 | t.strictEqual(route.method, 'GET')
|
493 | t.strictEqual(route.url, '/foo')
|
494 | t.strictEqual(route.logLevel, 'info')
|
495 | t.strictEqual(route.bodyLimit, 100)
|
496 | })
|
497 | instance.get('/foo', { logLevel: 'info', bodyLimit: 100 }, function (req, reply) {
|
498 | reply.send()
|
499 | })
|
500 | next()
|
501 | })
|
502 |
|
503 | fastify.ready(err => {
|
504 | t.error(err)
|
505 | })
|
506 | })
|
507 |
|
508 | test('onRoute hook should receive any route option', t => {
|
509 | t.plan(4)
|
510 | const fastify = Fastify()
|
511 | fastify.register((instance, opts, next) => {
|
512 | instance.addHook('onRoute', function (route) {
|
513 | t.strictEqual(route.method, 'GET')
|
514 | t.strictEqual(route.url, '/foo')
|
515 | t.strictEqual(route.auth, 'basic')
|
516 | })
|
517 | instance.get('/foo', { auth: 'basic' }, function (req, reply) {
|
518 | reply.send()
|
519 | })
|
520 | next()
|
521 | })
|
522 |
|
523 | fastify.ready(err => {
|
524 | t.error(err)
|
525 | })
|
526 | })
|
527 |
|
528 | test('onRoute hook should preserve system route configuration', t => {
|
529 | t.plan(4)
|
530 | const fastify = Fastify()
|
531 | fastify.register((instance, opts, next) => {
|
532 | instance.addHook('onRoute', function (route) {
|
533 | t.strictEqual(route.method, 'GET')
|
534 | t.strictEqual(route.url, '/foo')
|
535 | t.strictEqual(route.handler.length, 2)
|
536 | })
|
537 | instance.get('/foo', { url: '/bar', method: 'POST' }, function (req, reply) {
|
538 | reply.send()
|
539 | })
|
540 | next()
|
541 | })
|
542 |
|
543 | fastify.ready(err => {
|
544 | t.error(err)
|
545 | })
|
546 | })
|
547 |
|
548 | test('onRoute hook should preserve handler function in options of shorthand route system configuration', t => {
|
549 | t.plan(2)
|
550 |
|
551 | const handler = (req, reply) => {}
|
552 |
|
553 | const fastify = Fastify()
|
554 | fastify.register((instance, opts, next) => {
|
555 | instance.addHook('onRoute', function (route) {
|
556 | t.strictEqual(route.handler, handler)
|
557 | })
|
558 | instance.get('/foo', { handler })
|
559 | next()
|
560 | })
|
561 |
|
562 | fastify.ready(err => {
|
563 | t.error(err)
|
564 | })
|
565 | })
|
566 |
|
567 | test('onRoute hook that throws should be caught ', t => {
|
568 | t.plan(1)
|
569 | const fastify = Fastify()
|
570 |
|
571 | fastify.register((instance, opts, next) => {
|
572 | instance.addHook('onRoute', () => {
|
573 | throw new Error('snap')
|
574 | })
|
575 | instance.get('/', opts, function (req, reply) {
|
576 | reply.send()
|
577 | })
|
578 | next()
|
579 | })
|
580 |
|
581 | fastify.ready(err => {
|
582 | t.ok(err)
|
583 | })
|
584 | })
|
585 |
|
586 | test('onResponse hook should log request error', t => {
|
587 | t.plan(4)
|
588 |
|
589 | let fastify = null
|
590 | const logStream = split(JSON.parse)
|
591 | try {
|
592 | fastify = Fastify({
|
593 | logger: {
|
594 | stream: logStream,
|
595 | level: 'error'
|
596 | }
|
597 | })
|
598 | } catch (e) {
|
599 | t.fail()
|
600 | }
|
601 |
|
602 | logStream.once('data', line => {
|
603 | t.equal(line.msg, 'request errored')
|
604 | t.equal(line.level, 50)
|
605 | })
|
606 |
|
607 | fastify.addHook('onResponse', (request, reply, next) => {
|
608 | next(new Error('kaboom'))
|
609 | })
|
610 |
|
611 | fastify.get('/root', (request, reply) => {
|
612 | reply.send()
|
613 | })
|
614 |
|
615 | fastify.inject('/root', (err, res) => {
|
616 | t.error(err)
|
617 | t.strictEqual(res.statusCode, 200)
|
618 | })
|
619 | })
|
620 |
|
621 | test('onResponse hook should support encapsulation / 1', t => {
|
622 | t.plan(5)
|
623 | const fastify = Fastify()
|
624 |
|
625 | fastify.register((instance, opts, next) => {
|
626 | instance.addHook('onResponse', (request, reply, next) => {
|
627 | t.strictEqual(reply.plugin, true)
|
628 | next()
|
629 | })
|
630 |
|
631 | instance.get('/plugin', (request, reply) => {
|
632 | reply.plugin = true
|
633 | reply.send()
|
634 | })
|
635 |
|
636 | next()
|
637 | })
|
638 |
|
639 | fastify.get('/root', (request, reply) => {
|
640 | reply.send()
|
641 | })
|
642 |
|
643 | fastify.inject('/root', (err, res) => {
|
644 | t.error(err)
|
645 | t.strictEqual(res.statusCode, 200)
|
646 | })
|
647 |
|
648 | fastify.inject('/plugin', (err, res) => {
|
649 | t.error(err)
|
650 | t.strictEqual(res.statusCode, 200)
|
651 | })
|
652 | })
|
653 |
|
654 | test('onResponse hook should support encapsulation / 2', t => {
|
655 | t.plan(3)
|
656 | const fastify = Fastify()
|
657 | var pluginInstance
|
658 |
|
659 | fastify.addHook('onResponse', () => {})
|
660 |
|
661 | fastify.register((instance, opts, next) => {
|
662 | instance.addHook('onResponse', () => {})
|
663 | pluginInstance = instance
|
664 | next()
|
665 | })
|
666 |
|
667 | fastify.ready(err => {
|
668 | t.error(err)
|
669 | t.is(fastify[symbols.kHooks].onResponse.length, 1)
|
670 | t.is(pluginInstance[symbols.kHooks].onResponse.length, 2)
|
671 | })
|
672 | })
|
673 |
|
674 | test('onResponse hook should support encapsulation / 3', t => {
|
675 | t.plan(16)
|
676 | const fastify = Fastify()
|
677 | fastify.decorate('hello', 'world')
|
678 |
|
679 | fastify.addHook('onResponse', function (request, reply, next) {
|
680 | t.ok(this.hello)
|
681 | t.ok('onResponse called')
|
682 | next()
|
683 | })
|
684 |
|
685 | fastify.get('/first', (req, reply) => {
|
686 | reply.send({ hello: 'world' })
|
687 | })
|
688 |
|
689 | fastify.register((instance, opts, next) => {
|
690 | instance.decorate('hello2', 'world')
|
691 | instance.addHook('onResponse', function (request, reply, next) {
|
692 | t.ok(this.hello)
|
693 | t.ok(this.hello2)
|
694 | t.ok('onResponse called')
|
695 | next()
|
696 | })
|
697 |
|
698 | instance.get('/second', (req, reply) => {
|
699 | reply.send({ hello: 'world' })
|
700 | })
|
701 |
|
702 | next()
|
703 | })
|
704 |
|
705 | fastify.listen(0, err => {
|
706 | t.error(err)
|
707 | fastify.server.unref()
|
708 |
|
709 | sget({
|
710 | method: 'GET',
|
711 | url: 'http://localhost:' + fastify.server.address().port + '/first'
|
712 | }, (err, response, body) => {
|
713 | t.error(err)
|
714 | t.strictEqual(response.statusCode, 200)
|
715 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
716 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
717 | })
|
718 |
|
719 | sget({
|
720 | method: 'GET',
|
721 | url: 'http://localhost:' + fastify.server.address().port + '/second'
|
722 | }, (err, response, body) => {
|
723 | t.error(err)
|
724 | t.strictEqual(response.statusCode, 200)
|
725 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
726 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
727 | })
|
728 | })
|
729 | })
|
730 |
|
731 | test('onSend hook should support encapsulation / 1', t => {
|
732 | t.plan(3)
|
733 | const fastify = Fastify()
|
734 | var pluginInstance
|
735 |
|
736 | fastify.addHook('onSend', () => {})
|
737 |
|
738 | fastify.register((instance, opts, next) => {
|
739 | instance.addHook('onSend', () => {})
|
740 | pluginInstance = instance
|
741 | next()
|
742 | })
|
743 |
|
744 | fastify.ready(err => {
|
745 | t.error(err)
|
746 | t.is(fastify[symbols.kHooks].onSend.length, 1)
|
747 | t.is(pluginInstance[symbols.kHooks].onSend.length, 2)
|
748 | })
|
749 | })
|
750 |
|
751 | test('onSend hook should support encapsulation / 2', t => {
|
752 | t.plan(16)
|
753 | const fastify = Fastify()
|
754 | fastify.decorate('hello', 'world')
|
755 |
|
756 | fastify.addHook('onSend', function (request, reply, thePayload, next) {
|
757 | t.ok(this.hello)
|
758 | t.ok('onSend called')
|
759 | next()
|
760 | })
|
761 |
|
762 | fastify.get('/first', (req, reply) => {
|
763 | reply.send({ hello: 'world' })
|
764 | })
|
765 |
|
766 | fastify.register((instance, opts, next) => {
|
767 | instance.decorate('hello2', 'world')
|
768 | instance.addHook('onSend', function (request, reply, thePayload, next) {
|
769 | t.ok(this.hello)
|
770 | t.ok(this.hello2)
|
771 | t.ok('onSend called')
|
772 | next()
|
773 | })
|
774 |
|
775 | instance.get('/second', (req, reply) => {
|
776 | reply.send({ hello: 'world' })
|
777 | })
|
778 |
|
779 | next()
|
780 | })
|
781 |
|
782 | fastify.listen(0, err => {
|
783 | t.error(err)
|
784 | fastify.server.unref()
|
785 |
|
786 | sget({
|
787 | method: 'GET',
|
788 | url: 'http://localhost:' + fastify.server.address().port + '/first'
|
789 | }, (err, response, body) => {
|
790 | t.error(err)
|
791 | t.strictEqual(response.statusCode, 200)
|
792 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
793 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
794 | })
|
795 |
|
796 | sget({
|
797 | method: 'GET',
|
798 | url: 'http://localhost:' + fastify.server.address().port + '/second'
|
799 | }, (err, response, body) => {
|
800 | t.error(err)
|
801 | t.strictEqual(response.statusCode, 200)
|
802 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
803 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
804 | })
|
805 | })
|
806 | })
|
807 |
|
808 | test('onSend hook is called after payload is serialized and headers are set', t => {
|
809 | t.plan(30)
|
810 | const fastify = Fastify()
|
811 |
|
812 | fastify.register((instance, opts, next) => {
|
813 | const thePayload = { hello: 'world' }
|
814 |
|
815 | instance.addHook('onSend', function (request, reply, payload, next) {
|
816 | t.deepEqual(JSON.parse(payload), thePayload)
|
817 | t.strictEqual(reply[symbols.kReplyHeaders]['content-type'], 'application/json; charset=utf-8')
|
818 | next()
|
819 | })
|
820 |
|
821 | instance.get('/json', (request, reply) => {
|
822 | reply.send(thePayload)
|
823 | })
|
824 |
|
825 | next()
|
826 | })
|
827 |
|
828 | fastify.register((instance, opts, next) => {
|
829 | instance.addHook('onSend', function (request, reply, payload, next) {
|
830 | t.strictEqual(payload, 'some text')
|
831 | t.strictEqual(reply[symbols.kReplyHeaders]['content-type'], 'text/plain; charset=utf-8')
|
832 | next()
|
833 | })
|
834 |
|
835 | instance.get('/text', (request, reply) => {
|
836 | reply.send('some text')
|
837 | })
|
838 |
|
839 | next()
|
840 | })
|
841 |
|
842 | fastify.register((instance, opts, next) => {
|
843 | const thePayload = Buffer.from('buffer payload')
|
844 |
|
845 | instance.addHook('onSend', function (request, reply, payload, next) {
|
846 | t.strictEqual(payload, thePayload)
|
847 | t.strictEqual(reply[symbols.kReplyHeaders]['content-type'], 'application/octet-stream')
|
848 | next()
|
849 | })
|
850 |
|
851 | instance.get('/buffer', (request, reply) => {
|
852 | reply.send(thePayload)
|
853 | })
|
854 |
|
855 | next()
|
856 | })
|
857 |
|
858 | fastify.register((instance, opts, next) => {
|
859 | var chunk = 'stream payload'
|
860 | const thePayload = new stream.Readable({
|
861 | read () {
|
862 | this.push(chunk)
|
863 | chunk = null
|
864 | }
|
865 | })
|
866 |
|
867 | instance.addHook('onSend', function (request, reply, payload, next) {
|
868 | t.strictEqual(payload, thePayload)
|
869 | t.strictEqual(reply[symbols.kReplyHeaders]['content-type'], 'application/octet-stream')
|
870 | next()
|
871 | })
|
872 |
|
873 | instance.get('/stream', (request, reply) => {
|
874 | reply.send(thePayload)
|
875 | })
|
876 |
|
877 | next()
|
878 | })
|
879 |
|
880 | fastify.register((instance, opts, next) => {
|
881 | const serializedPayload = 'serialized'
|
882 |
|
883 | instance.addHook('onSend', function (request, reply, payload, next) {
|
884 | t.strictEqual(payload, serializedPayload)
|
885 | t.strictEqual(reply[symbols.kReplyHeaders]['content-type'], 'text/custom')
|
886 | next()
|
887 | })
|
888 |
|
889 | instance.get('/custom-serializer', (request, reply) => {
|
890 | reply
|
891 | .serializer(() => serializedPayload)
|
892 | .type('text/custom')
|
893 | .send('needs to be serialized')
|
894 | })
|
895 |
|
896 | next()
|
897 | })
|
898 |
|
899 | fastify.inject({
|
900 | method: 'GET',
|
901 | url: '/json'
|
902 | }, (err, res) => {
|
903 | t.error(err)
|
904 | t.strictEqual(res.statusCode, 200)
|
905 | t.deepEqual(JSON.parse(res.payload), { hello: 'world' })
|
906 | t.strictEqual(res.headers['content-length'], '17')
|
907 | })
|
908 |
|
909 | fastify.inject({
|
910 | method: 'GET',
|
911 | url: '/text'
|
912 | }, (err, res) => {
|
913 | t.error(err)
|
914 | t.strictEqual(res.statusCode, 200)
|
915 | t.deepEqual(res.payload, 'some text')
|
916 | t.strictEqual(res.headers['content-length'], '9')
|
917 | })
|
918 |
|
919 | fastify.inject({
|
920 | method: 'GET',
|
921 | url: '/buffer'
|
922 | }, (err, res) => {
|
923 | t.error(err)
|
924 | t.strictEqual(res.statusCode, 200)
|
925 | t.deepEqual(res.payload, 'buffer payload')
|
926 | t.strictEqual(res.headers['content-length'], '14')
|
927 | })
|
928 |
|
929 | fastify.inject({
|
930 | method: 'GET',
|
931 | url: '/stream'
|
932 | }, (err, res) => {
|
933 | t.error(err)
|
934 | t.strictEqual(res.statusCode, 200)
|
935 | t.deepEqual(res.payload, 'stream payload')
|
936 | t.strictEqual(res.headers['transfer-encoding'], 'chunked')
|
937 | })
|
938 |
|
939 | fastify.inject({
|
940 | method: 'GET',
|
941 | url: '/custom-serializer'
|
942 | }, (err, res) => {
|
943 | t.error(err)
|
944 | t.strictEqual(res.statusCode, 200)
|
945 | t.deepEqual(res.payload, 'serialized')
|
946 | t.strictEqual(res.headers['content-type'], 'text/custom')
|
947 | })
|
948 | })
|
949 |
|
950 | test('modify payload', t => {
|
951 | t.plan(10)
|
952 | const fastify = Fastify()
|
953 | const payload = { hello: 'world' }
|
954 | const modifiedPayload = { hello: 'modified' }
|
955 | const anotherPayload = '"winter is coming"'
|
956 |
|
957 | fastify.addHook('onSend', function (request, reply, thePayload, next) {
|
958 | t.ok('onSend called')
|
959 | t.deepEqual(JSON.parse(thePayload), payload)
|
960 | thePayload = thePayload.replace('world', 'modified')
|
961 | next(null, thePayload)
|
962 | })
|
963 |
|
964 | fastify.addHook('onSend', function (request, reply, thePayload, next) {
|
965 | t.ok('onSend called')
|
966 | t.deepEqual(JSON.parse(thePayload), modifiedPayload)
|
967 | next(null, anotherPayload)
|
968 | })
|
969 |
|
970 | fastify.addHook('onSend', function (request, reply, thePayload, next) {
|
971 | t.ok('onSend called')
|
972 | t.strictEqual(thePayload, anotherPayload)
|
973 | next()
|
974 | })
|
975 |
|
976 | fastify.get('/', (req, reply) => {
|
977 | reply.send(payload)
|
978 | })
|
979 |
|
980 | fastify.inject({
|
981 | method: 'GET',
|
982 | url: '/'
|
983 | }, (err, res) => {
|
984 | t.error(err)
|
985 | t.strictEqual(res.payload, anotherPayload)
|
986 | t.strictEqual(res.statusCode, 200)
|
987 | t.strictEqual(res.headers['content-length'], '18')
|
988 | })
|
989 | })
|
990 |
|
991 | test('clear payload', t => {
|
992 | t.plan(6)
|
993 | const fastify = Fastify()
|
994 |
|
995 | fastify.addHook('onSend', function (request, reply, payload, next) {
|
996 | t.ok('onSend called')
|
997 | reply.code(304)
|
998 | next(null, null)
|
999 | })
|
1000 |
|
1001 | fastify.get('/', (req, reply) => {
|
1002 | reply.send({ hello: 'world' })
|
1003 | })
|
1004 |
|
1005 | fastify.inject({
|
1006 | method: 'GET',
|
1007 | url: '/'
|
1008 | }, (err, res) => {
|
1009 | t.error(err)
|
1010 | t.strictEqual(res.statusCode, 304)
|
1011 | t.strictEqual(res.payload, '')
|
1012 | t.strictEqual(res.headers['content-length'], undefined)
|
1013 | t.strictEqual(res.headers['content-type'], 'application/json; charset=utf-8')
|
1014 | })
|
1015 | })
|
1016 |
|
1017 | test('onSend hook throws', t => {
|
1018 | t.plan(7)
|
1019 | const fastify = Fastify()
|
1020 | fastify.addHook('onSend', function (request, reply, payload, next) {
|
1021 | if (request.raw.method === 'DELETE') {
|
1022 | next(new Error('some error'))
|
1023 | return
|
1024 | }
|
1025 | next()
|
1026 | })
|
1027 |
|
1028 | fastify.get('/', (req, reply) => {
|
1029 | reply.send({ hello: 'world' })
|
1030 | })
|
1031 |
|
1032 | fastify.delete('/', (req, reply) => {
|
1033 | reply.send({ hello: 'world' })
|
1034 | })
|
1035 |
|
1036 | fastify.listen(0, err => {
|
1037 | t.error(err)
|
1038 | fastify.server.unref()
|
1039 | sget({
|
1040 | method: 'GET',
|
1041 | url: 'http://localhost:' + fastify.server.address().port
|
1042 | }, (err, response, body) => {
|
1043 | t.error(err)
|
1044 | t.strictEqual(response.statusCode, 200)
|
1045 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
1046 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
1047 | })
|
1048 | sget({
|
1049 | method: 'DELETE',
|
1050 | url: 'http://localhost:' + fastify.server.address().port
|
1051 | }, (err, response, body) => {
|
1052 | t.error(err)
|
1053 | t.strictEqual(response.statusCode, 500)
|
1054 | })
|
1055 | })
|
1056 | })
|
1057 |
|
1058 | test('onSend hook should receive valid request and reply objects if onRequest hook fails', t => {
|
1059 | t.plan(4)
|
1060 | const fastify = Fastify()
|
1061 |
|
1062 | fastify.decorateRequest('testDecorator', 'testDecoratorVal')
|
1063 | fastify.decorateReply('testDecorator', 'testDecoratorVal')
|
1064 |
|
1065 | fastify.addHook('onRequest', function (req, reply, next) {
|
1066 | next(new Error('onRequest hook failed'))
|
1067 | })
|
1068 |
|
1069 | fastify.addHook('onSend', function (request, reply, payload, next) {
|
1070 | t.strictEqual(request.testDecorator, 'testDecoratorVal')
|
1071 | t.strictEqual(reply.testDecorator, 'testDecoratorVal')
|
1072 | next()
|
1073 | })
|
1074 |
|
1075 | fastify.get('/', (req, reply) => {
|
1076 | reply.send('hello')
|
1077 | })
|
1078 |
|
1079 | fastify.inject({
|
1080 | method: 'GET',
|
1081 | url: '/'
|
1082 | }, (err, res) => {
|
1083 | t.error(err)
|
1084 | t.strictEqual(res.statusCode, 500)
|
1085 | })
|
1086 | })
|
1087 |
|
1088 | test('onSend hook should receive valid request and reply objects if middleware fails', t => {
|
1089 | t.plan(4)
|
1090 | const fastify = Fastify()
|
1091 |
|
1092 | fastify.decorateRequest('testDecorator', 'testDecoratorVal')
|
1093 | fastify.decorateReply('testDecorator', 'testDecoratorVal')
|
1094 |
|
1095 | fastify.use(function (req, res, next) {
|
1096 | next(new Error('middlware failed'))
|
1097 | })
|
1098 |
|
1099 | fastify.addHook('onSend', function (request, reply, payload, next) {
|
1100 | t.strictEqual(request.testDecorator, 'testDecoratorVal')
|
1101 | t.strictEqual(reply.testDecorator, 'testDecoratorVal')
|
1102 | next()
|
1103 | })
|
1104 |
|
1105 | fastify.get('/', (req, reply) => {
|
1106 | reply.send('hello')
|
1107 | })
|
1108 |
|
1109 | fastify.inject({
|
1110 | method: 'GET',
|
1111 | url: '/'
|
1112 | }, (err, res) => {
|
1113 | t.error(err)
|
1114 | t.strictEqual(res.statusCode, 500)
|
1115 | })
|
1116 | })
|
1117 |
|
1118 | test('onSend hook should receive valid request and reply objects if a custom content type parser fails', t => {
|
1119 | t.plan(4)
|
1120 | const fastify = Fastify()
|
1121 |
|
1122 | fastify.decorateRequest('testDecorator', 'testDecoratorVal')
|
1123 | fastify.decorateReply('testDecorator', 'testDecoratorVal')
|
1124 |
|
1125 | fastify.addContentTypeParser('*', function (req, done) {
|
1126 | done(new Error('content type parser failed'))
|
1127 | })
|
1128 |
|
1129 | fastify.addHook('onSend', function (request, reply, payload, next) {
|
1130 | t.strictEqual(request.testDecorator, 'testDecoratorVal')
|
1131 | t.strictEqual(reply.testDecorator, 'testDecoratorVal')
|
1132 | next()
|
1133 | })
|
1134 |
|
1135 | fastify.get('/', (req, reply) => {
|
1136 | reply.send('hello')
|
1137 | })
|
1138 |
|
1139 | fastify.inject({
|
1140 | method: 'POST',
|
1141 | url: '/',
|
1142 | payload: 'body'
|
1143 | }, (err, res) => {
|
1144 | t.error(err)
|
1145 | t.strictEqual(res.statusCode, 500)
|
1146 | })
|
1147 | })
|
1148 |
|
1149 | test('cannot add hook after binding', t => {
|
1150 | t.plan(2)
|
1151 | const instance = Fastify()
|
1152 |
|
1153 | instance.get('/', function (request, reply) {
|
1154 | reply.send({ hello: 'world' })
|
1155 | })
|
1156 |
|
1157 | instance.listen(0, err => {
|
1158 | t.error(err)
|
1159 | t.tearDown(instance.server.close.bind(instance.server))
|
1160 |
|
1161 | try {
|
1162 | instance.addHook('onRequest', () => {})
|
1163 | t.fail()
|
1164 | } catch (e) {
|
1165 | t.pass()
|
1166 | }
|
1167 | })
|
1168 | })
|
1169 |
|
1170 | test('onRequest hooks should be able to block a request', t => {
|
1171 | t.plan(5)
|
1172 | const fastify = Fastify()
|
1173 |
|
1174 | fastify.addHook('onRequest', (req, reply, next) => {
|
1175 | reply.send('hello')
|
1176 | next()
|
1177 | })
|
1178 |
|
1179 | fastify.addHook('onRequest', (req, reply, next) => {
|
1180 | t.fail('this should not be called')
|
1181 | })
|
1182 |
|
1183 | fastify.addHook('preHandler', (req, reply, next) => {
|
1184 | t.fail('this should not be called')
|
1185 | })
|
1186 |
|
1187 | fastify.addHook('onSend', (req, reply, payload, next) => {
|
1188 | t.ok('called')
|
1189 | next()
|
1190 | })
|
1191 |
|
1192 | fastify.addHook('onResponse', (request, reply, next) => {
|
1193 | t.ok('called')
|
1194 | next()
|
1195 | })
|
1196 |
|
1197 | fastify.get('/', function (request, reply) {
|
1198 | t.fail('we should not be here')
|
1199 | })
|
1200 |
|
1201 | fastify.inject({
|
1202 | url: '/',
|
1203 | method: 'GET'
|
1204 | }, (err, res) => {
|
1205 | t.error(err)
|
1206 | t.is(res.statusCode, 200)
|
1207 | t.is(res.payload, 'hello')
|
1208 | })
|
1209 | })
|
1210 |
|
1211 | test('preValidation hooks should be able to block a request', t => {
|
1212 | t.plan(5)
|
1213 | const fastify = Fastify()
|
1214 |
|
1215 | fastify.addHook('preValidation', (req, reply, next) => {
|
1216 | reply.send('hello')
|
1217 | next()
|
1218 | })
|
1219 |
|
1220 | fastify.addHook('preValidation', (req, reply, next) => {
|
1221 | t.fail('this should not be called')
|
1222 | })
|
1223 |
|
1224 | fastify.addHook('preHandler', (req, reply, next) => {
|
1225 | t.fail('this should not be called')
|
1226 | })
|
1227 |
|
1228 | fastify.addHook('onSend', (req, reply, payload, next) => {
|
1229 | t.ok('called')
|
1230 | next()
|
1231 | })
|
1232 |
|
1233 | fastify.addHook('onResponse', (request, reply, next) => {
|
1234 | t.ok('called')
|
1235 | next()
|
1236 | })
|
1237 |
|
1238 | fastify.get('/', function (request, reply) {
|
1239 | t.fail('we should not be here')
|
1240 | })
|
1241 |
|
1242 | fastify.inject({
|
1243 | url: '/',
|
1244 | method: 'GET'
|
1245 | }, (err, res) => {
|
1246 | t.error(err)
|
1247 | t.is(res.statusCode, 200)
|
1248 | t.is(res.payload, 'hello')
|
1249 | })
|
1250 | })
|
1251 |
|
1252 | test('preParsing hooks should be able to block a request', t => {
|
1253 | t.plan(5)
|
1254 | const fastify = Fastify()
|
1255 |
|
1256 | fastify.addHook('preParsing', (req, reply, next) => {
|
1257 | reply.send('hello')
|
1258 | next()
|
1259 | })
|
1260 |
|
1261 | fastify.addHook('preParsing', (req, reply, next) => {
|
1262 | t.fail('this should not be called')
|
1263 | })
|
1264 |
|
1265 | fastify.addHook('preHandler', (req, reply, next) => {
|
1266 | t.fail('this should not be called')
|
1267 | })
|
1268 |
|
1269 | fastify.addHook('onSend', (req, reply, payload, next) => {
|
1270 | t.ok('called')
|
1271 | next()
|
1272 | })
|
1273 |
|
1274 | fastify.addHook('onResponse', (request, reply, next) => {
|
1275 | t.ok('called')
|
1276 | next()
|
1277 | })
|
1278 |
|
1279 | fastify.get('/', function (request, reply) {
|
1280 | t.fail('we should not be here')
|
1281 | })
|
1282 |
|
1283 | fastify.inject({
|
1284 | url: '/',
|
1285 | method: 'GET'
|
1286 | }, (err, res) => {
|
1287 | t.error(err)
|
1288 | t.is(res.statusCode, 200)
|
1289 | t.is(res.payload, 'hello')
|
1290 | })
|
1291 | })
|
1292 |
|
1293 | test('preHandler hooks should be able to block a request', t => {
|
1294 | t.plan(5)
|
1295 | const fastify = Fastify()
|
1296 |
|
1297 | fastify.addHook('preHandler', (req, reply, next) => {
|
1298 | reply.send('hello')
|
1299 | next()
|
1300 | })
|
1301 |
|
1302 | fastify.addHook('preHandler', (req, reply, next) => {
|
1303 | t.fail('this should not be called')
|
1304 | })
|
1305 |
|
1306 | fastify.addHook('onSend', (req, reply, payload, next) => {
|
1307 | t.equal(payload, 'hello')
|
1308 | next()
|
1309 | })
|
1310 |
|
1311 | fastify.addHook('onResponse', (request, reply, next) => {
|
1312 | t.ok('called')
|
1313 | next()
|
1314 | })
|
1315 |
|
1316 | fastify.get('/', function (request, reply) {
|
1317 | t.fail('we should not be here')
|
1318 | })
|
1319 |
|
1320 | fastify.inject({
|
1321 | url: '/',
|
1322 | method: 'GET'
|
1323 | }, (err, res) => {
|
1324 | t.error(err)
|
1325 | t.is(res.statusCode, 200)
|
1326 | t.is(res.payload, 'hello')
|
1327 | })
|
1328 | })
|
1329 |
|
1330 | test('onRequest hooks should be able to block a request (last hook)', t => {
|
1331 | t.plan(5)
|
1332 | const fastify = Fastify()
|
1333 |
|
1334 | fastify.addHook('onRequest', (req, reply, next) => {
|
1335 | reply.send('hello')
|
1336 | next()
|
1337 | })
|
1338 |
|
1339 | fastify.addHook('preHandler', (req, reply, next) => {
|
1340 | t.fail('this should not be called')
|
1341 | })
|
1342 |
|
1343 | fastify.addHook('onSend', (req, reply, payload, next) => {
|
1344 | t.ok('called')
|
1345 | next()
|
1346 | })
|
1347 |
|
1348 | fastify.addHook('onResponse', (request, reply, next) => {
|
1349 | t.ok('called')
|
1350 | next()
|
1351 | })
|
1352 |
|
1353 | fastify.get('/', function (request, reply) {
|
1354 | t.fail('we should not be here')
|
1355 | })
|
1356 |
|
1357 | fastify.inject({
|
1358 | url: '/',
|
1359 | method: 'GET'
|
1360 | }, (err, res) => {
|
1361 | t.error(err)
|
1362 | t.is(res.statusCode, 200)
|
1363 | t.is(res.payload, 'hello')
|
1364 | })
|
1365 | })
|
1366 |
|
1367 | test('preHandler hooks should be able to block a request (last hook)', t => {
|
1368 | t.plan(5)
|
1369 | const fastify = Fastify()
|
1370 |
|
1371 | fastify.addHook('preHandler', (req, reply, next) => {
|
1372 | reply.send('hello')
|
1373 | next()
|
1374 | })
|
1375 |
|
1376 | fastify.addHook('onSend', (req, reply, payload, next) => {
|
1377 | t.equal(payload, 'hello')
|
1378 | next()
|
1379 | })
|
1380 |
|
1381 | fastify.addHook('onResponse', (request, reply, next) => {
|
1382 | t.ok('called')
|
1383 | next()
|
1384 | })
|
1385 |
|
1386 | fastify.get('/', function (request, reply) {
|
1387 | t.fail('we should not be here')
|
1388 | })
|
1389 |
|
1390 | fastify.inject({
|
1391 | url: '/',
|
1392 | method: 'GET'
|
1393 | }, (err, res) => {
|
1394 | t.error(err)
|
1395 | t.is(res.statusCode, 200)
|
1396 | t.is(res.payload, 'hello')
|
1397 | })
|
1398 | })
|
1399 |
|
1400 | test('onRequest respond with a stream', t => {
|
1401 | t.plan(4)
|
1402 | const fastify = Fastify()
|
1403 |
|
1404 | fastify.addHook('onRequest', (req, reply, next) => {
|
1405 | const stream = fs.createReadStream(process.cwd() + '/test/stream.test.js', 'utf8')
|
1406 |
|
1407 |
|
1408 | reply.send(stream)
|
1409 | })
|
1410 |
|
1411 | fastify.addHook('onRequest', (req, res, next) => {
|
1412 | t.fail('this should not be called')
|
1413 | })
|
1414 |
|
1415 | fastify.addHook('preHandler', (req, reply, next) => {
|
1416 | t.fail('this should not be called')
|
1417 | })
|
1418 |
|
1419 | fastify.addHook('onSend', (req, reply, payload, next) => {
|
1420 | t.ok('called')
|
1421 | next()
|
1422 | })
|
1423 |
|
1424 | fastify.addHook('onResponse', (request, reply, next) => {
|
1425 | t.ok('called')
|
1426 | next()
|
1427 | })
|
1428 |
|
1429 | fastify.get('/', function (request, reply) {
|
1430 | t.fail('we should not be here')
|
1431 | })
|
1432 |
|
1433 | fastify.inject({
|
1434 | url: '/',
|
1435 | method: 'GET'
|
1436 | }, (err, res) => {
|
1437 | t.error(err)
|
1438 | t.is(res.statusCode, 200)
|
1439 | })
|
1440 | })
|
1441 |
|
1442 | test('preHandler respond with a stream', t => {
|
1443 | t.plan(7)
|
1444 | const fastify = Fastify()
|
1445 |
|
1446 | fastify.addHook('onRequest', (req, reply, next) => {
|
1447 | t.ok('called')
|
1448 | next()
|
1449 | })
|
1450 |
|
1451 |
|
1452 |
|
1453 | const order = [1, 2]
|
1454 |
|
1455 | fastify.addHook('preHandler', (req, reply, next) => {
|
1456 | const stream = fs.createReadStream(process.cwd() + '/test/stream.test.js', 'utf8')
|
1457 | reply.send(stream)
|
1458 | reply.res.once('finish', () => {
|
1459 | t.is(order.shift(), 2)
|
1460 | next()
|
1461 | })
|
1462 | })
|
1463 |
|
1464 | fastify.addHook('preHandler', (req, reply, next) => {
|
1465 | t.fail('this should not be called')
|
1466 | })
|
1467 |
|
1468 | fastify.addHook('onSend', (req, reply, payload, next) => {
|
1469 | t.is(order.shift(), 1)
|
1470 | t.is(typeof payload.pipe, 'function')
|
1471 | next()
|
1472 | })
|
1473 |
|
1474 | fastify.addHook('onResponse', (request, reply, next) => {
|
1475 | t.ok('called')
|
1476 | next()
|
1477 | })
|
1478 |
|
1479 | fastify.get('/', function (request, reply) {
|
1480 | t.fail('we should not be here')
|
1481 | })
|
1482 |
|
1483 | fastify.inject({
|
1484 | url: '/',
|
1485 | method: 'GET'
|
1486 | }, (err, res) => {
|
1487 | t.error(err)
|
1488 | t.is(res.statusCode, 200)
|
1489 | })
|
1490 | })
|
1491 |
|
1492 | test('Register an hook after a plugin inside a plugin', t => {
|
1493 | t.plan(6)
|
1494 | const fastify = Fastify()
|
1495 |
|
1496 | fastify.register(fp(function (instance, opts, next) {
|
1497 | instance.addHook('preHandler', function (req, reply, next) {
|
1498 | t.ok('called')
|
1499 | next()
|
1500 | })
|
1501 |
|
1502 | instance.get('/', function (request, reply) {
|
1503 | reply.send({ hello: 'world' })
|
1504 | })
|
1505 |
|
1506 | next()
|
1507 | }))
|
1508 |
|
1509 | fastify.register(fp(function (instance, opts, next) {
|
1510 | instance.addHook('preHandler', function (req, reply, next) {
|
1511 | t.ok('called')
|
1512 | next()
|
1513 | })
|
1514 |
|
1515 | instance.addHook('preHandler', function (req, reply, next) {
|
1516 | t.ok('called')
|
1517 | next()
|
1518 | })
|
1519 |
|
1520 | next()
|
1521 | }))
|
1522 |
|
1523 | fastify.inject({
|
1524 | url: '/',
|
1525 | method: 'GET'
|
1526 | }, (err, res) => {
|
1527 | t.error(err)
|
1528 | t.is(res.statusCode, 200)
|
1529 | t.deepEqual(JSON.parse(res.payload), { hello: 'world' })
|
1530 | })
|
1531 | })
|
1532 |
|
1533 | test('Register an hook after a plugin inside a plugin (with preHandler option)', t => {
|
1534 | t.plan(7)
|
1535 | const fastify = Fastify()
|
1536 |
|
1537 | fastify.register(fp(function (instance, opts, next) {
|
1538 | instance.addHook('preHandler', function (req, reply, next) {
|
1539 | t.ok('called')
|
1540 | next()
|
1541 | })
|
1542 |
|
1543 | instance.get('/', {
|
1544 | preHandler: (req, reply, next) => {
|
1545 | t.ok('called')
|
1546 | next()
|
1547 | }
|
1548 | }, function (request, reply) {
|
1549 | reply.send({ hello: 'world' })
|
1550 | })
|
1551 |
|
1552 | next()
|
1553 | }))
|
1554 |
|
1555 | fastify.register(fp(function (instance, opts, next) {
|
1556 | instance.addHook('preHandler', function (req, reply, next) {
|
1557 | t.ok('called')
|
1558 | next()
|
1559 | })
|
1560 |
|
1561 | instance.addHook('preHandler', function (req, reply, next) {
|
1562 | t.ok('called')
|
1563 | next()
|
1564 | })
|
1565 |
|
1566 | next()
|
1567 | }))
|
1568 |
|
1569 | fastify.inject({
|
1570 | url: '/',
|
1571 | method: 'GET'
|
1572 | }, (err, res) => {
|
1573 | t.error(err)
|
1574 | t.is(res.statusCode, 200)
|
1575 | t.deepEqual(JSON.parse(res.payload), { hello: 'world' })
|
1576 | })
|
1577 | })
|
1578 |
|
1579 | test('Register hooks inside a plugin after an encapsulated plugin', t => {
|
1580 | t.plan(7)
|
1581 | const fastify = Fastify()
|
1582 |
|
1583 | fastify.register(function (instance, opts, next) {
|
1584 | instance.get('/', function (request, reply) {
|
1585 | reply.send({ hello: 'world' })
|
1586 | })
|
1587 |
|
1588 | next()
|
1589 | })
|
1590 |
|
1591 | fastify.register(fp(function (instance, opts, next) {
|
1592 | instance.addHook('onRequest', function (req, reply, next) {
|
1593 | t.ok('called')
|
1594 | next()
|
1595 | })
|
1596 |
|
1597 | instance.addHook('preHandler', function (request, reply, next) {
|
1598 | t.ok('called')
|
1599 | next()
|
1600 | })
|
1601 |
|
1602 | instance.addHook('onSend', function (request, reply, payload, next) {
|
1603 | t.ok('called')
|
1604 | next()
|
1605 | })
|
1606 |
|
1607 | instance.addHook('onResponse', function (request, reply, next) {
|
1608 | t.ok('called')
|
1609 | next()
|
1610 | })
|
1611 |
|
1612 | next()
|
1613 | }))
|
1614 |
|
1615 | fastify.inject('/', (err, res) => {
|
1616 | t.error(err)
|
1617 | t.is(res.statusCode, 200)
|
1618 | t.deepEqual(JSON.parse(res.payload), { hello: 'world' })
|
1619 | })
|
1620 | })
|
1621 |
|
1622 | test('onRequest hooks should run in the order in which they are defined', t => {
|
1623 | t.plan(9)
|
1624 | const fastify = Fastify()
|
1625 |
|
1626 | fastify.register(function (instance, opts, next) {
|
1627 | instance.addHook('onRequest', function (req, reply, next) {
|
1628 | t.strictEqual(req.previous, undefined)
|
1629 | req.previous = 1
|
1630 | next()
|
1631 | })
|
1632 |
|
1633 | instance.get('/', function (request, reply) {
|
1634 | t.strictEqual(request.previous, 5)
|
1635 | reply.send({ hello: 'world' })
|
1636 | })
|
1637 |
|
1638 | instance.register(fp(function (i, opts, next) {
|
1639 | i.addHook('onRequest', function (req, reply, next) {
|
1640 | t.strictEqual(req.previous, 1)
|
1641 | req.previous = 2
|
1642 | next()
|
1643 | })
|
1644 | next()
|
1645 | }))
|
1646 |
|
1647 | next()
|
1648 | })
|
1649 |
|
1650 | fastify.register(fp(function (instance, opts, next) {
|
1651 | instance.addHook('onRequest', function (req, reply, next) {
|
1652 | t.strictEqual(req.previous, 2)
|
1653 | req.previous = 3
|
1654 | next()
|
1655 | })
|
1656 |
|
1657 | instance.register(fp(function (i, opts, next) {
|
1658 | i.addHook('onRequest', function (req, reply, next) {
|
1659 | t.strictEqual(req.previous, 3)
|
1660 | req.previous = 4
|
1661 | next()
|
1662 | })
|
1663 | next()
|
1664 | }))
|
1665 |
|
1666 | instance.addHook('onRequest', function (req, reply, next) {
|
1667 | t.strictEqual(req.previous, 4)
|
1668 | req.previous = 5
|
1669 | next()
|
1670 | })
|
1671 |
|
1672 | next()
|
1673 | }))
|
1674 |
|
1675 | fastify.inject('/', (err, res) => {
|
1676 | t.error(err)
|
1677 | t.strictEqual(res.statusCode, 200)
|
1678 | t.deepEqual(JSON.parse(res.payload), { hello: 'world' })
|
1679 | })
|
1680 | })
|
1681 |
|
1682 | test('preHandler hooks should run in the order in which they are defined', t => {
|
1683 | t.plan(9)
|
1684 | const fastify = Fastify()
|
1685 |
|
1686 | fastify.register(function (instance, opts, next) {
|
1687 | instance.addHook('preHandler', function (request, reply, next) {
|
1688 | t.strictEqual(request.previous, undefined)
|
1689 | request.previous = 1
|
1690 | next()
|
1691 | })
|
1692 |
|
1693 | instance.get('/', function (request, reply) {
|
1694 | t.strictEqual(request.previous, 5)
|
1695 | reply.send({ hello: 'world' })
|
1696 | })
|
1697 |
|
1698 | instance.register(fp(function (i, opts, next) {
|
1699 | i.addHook('preHandler', function (request, reply, next) {
|
1700 | t.strictEqual(request.previous, 1)
|
1701 | request.previous = 2
|
1702 | next()
|
1703 | })
|
1704 | next()
|
1705 | }))
|
1706 |
|
1707 | next()
|
1708 | })
|
1709 |
|
1710 | fastify.register(fp(function (instance, opts, next) {
|
1711 | instance.addHook('preHandler', function (request, reply, next) {
|
1712 | t.strictEqual(request.previous, 2)
|
1713 | request.previous = 3
|
1714 | next()
|
1715 | })
|
1716 |
|
1717 | instance.register(fp(function (i, opts, next) {
|
1718 | i.addHook('preHandler', function (request, reply, next) {
|
1719 | t.strictEqual(request.previous, 3)
|
1720 | request.previous = 4
|
1721 | next()
|
1722 | })
|
1723 | next()
|
1724 | }))
|
1725 |
|
1726 | instance.addHook('preHandler', function (request, reply, next) {
|
1727 | t.strictEqual(request.previous, 4)
|
1728 | request.previous = 5
|
1729 | next()
|
1730 | })
|
1731 |
|
1732 | next()
|
1733 | }))
|
1734 |
|
1735 | fastify.inject('/', (err, res) => {
|
1736 | t.error(err)
|
1737 | t.strictEqual(res.statusCode, 200)
|
1738 | t.deepEqual(JSON.parse(res.payload), { hello: 'world' })
|
1739 | })
|
1740 | })
|
1741 |
|
1742 | test('onSend hooks should run in the order in which they are defined', t => {
|
1743 | t.plan(8)
|
1744 | const fastify = Fastify()
|
1745 |
|
1746 | fastify.register(function (instance, opts, next) {
|
1747 | instance.addHook('onSend', function (request, reply, payload, next) {
|
1748 | t.strictEqual(request.previous, undefined)
|
1749 | request.previous = 1
|
1750 | next()
|
1751 | })
|
1752 |
|
1753 | instance.get('/', function (request, reply) {
|
1754 | reply.send({})
|
1755 | })
|
1756 |
|
1757 | instance.register(fp(function (i, opts, next) {
|
1758 | i.addHook('onSend', function (request, reply, payload, next) {
|
1759 | t.strictEqual(request.previous, 1)
|
1760 | request.previous = 2
|
1761 | next()
|
1762 | })
|
1763 | next()
|
1764 | }))
|
1765 |
|
1766 | next()
|
1767 | })
|
1768 |
|
1769 | fastify.register(fp(function (instance, opts, next) {
|
1770 | instance.addHook('onSend', function (request, reply, payload, next) {
|
1771 | t.strictEqual(request.previous, 2)
|
1772 | request.previous = 3
|
1773 | next()
|
1774 | })
|
1775 |
|
1776 | instance.register(fp(function (i, opts, next) {
|
1777 | i.addHook('onSend', function (request, reply, payload, next) {
|
1778 | t.strictEqual(request.previous, 3)
|
1779 | request.previous = 4
|
1780 | next()
|
1781 | })
|
1782 | next()
|
1783 | }))
|
1784 |
|
1785 | instance.addHook('onSend', function (request, reply, payload, next) {
|
1786 | t.strictEqual(request.previous, 4)
|
1787 | next(null, '5')
|
1788 | })
|
1789 |
|
1790 | next()
|
1791 | }))
|
1792 |
|
1793 | fastify.inject('/', (err, res) => {
|
1794 | t.error(err)
|
1795 | t.strictEqual(res.statusCode, 200)
|
1796 | t.deepEqual(JSON.parse(res.payload), 5)
|
1797 | })
|
1798 | })
|
1799 |
|
1800 | test('onResponse hooks should run in the order in which they are defined', t => {
|
1801 | t.plan(8)
|
1802 | const fastify = Fastify()
|
1803 |
|
1804 | fastify.register(function (instance, opts, next) {
|
1805 | instance.addHook('onResponse', function (request, reply, next) {
|
1806 | t.strictEqual(reply.previous, undefined)
|
1807 | reply.previous = 1
|
1808 | next()
|
1809 | })
|
1810 |
|
1811 | instance.get('/', function (request, reply) {
|
1812 | reply.send({ hello: 'world' })
|
1813 | })
|
1814 |
|
1815 | instance.register(fp(function (i, opts, next) {
|
1816 | i.addHook('onResponse', function (request, reply, next) {
|
1817 | t.strictEqual(reply.previous, 1)
|
1818 | reply.previous = 2
|
1819 | next()
|
1820 | })
|
1821 | next()
|
1822 | }))
|
1823 |
|
1824 | next()
|
1825 | })
|
1826 |
|
1827 | fastify.register(fp(function (instance, opts, next) {
|
1828 | instance.addHook('onResponse', function (request, reply, next) {
|
1829 | t.strictEqual(reply.previous, 2)
|
1830 | reply.previous = 3
|
1831 | next()
|
1832 | })
|
1833 |
|
1834 | instance.register(fp(function (i, opts, next) {
|
1835 | i.addHook('onResponse', function (request, reply, next) {
|
1836 | t.strictEqual(reply.previous, 3)
|
1837 | reply.previous = 4
|
1838 | next()
|
1839 | })
|
1840 | next()
|
1841 | }))
|
1842 |
|
1843 | instance.addHook('onResponse', function (request, reply, next) {
|
1844 | t.strictEqual(reply.previous, 4)
|
1845 | next()
|
1846 | })
|
1847 |
|
1848 | next()
|
1849 | }))
|
1850 |
|
1851 | fastify.inject('/', (err, res) => {
|
1852 | t.error(err)
|
1853 | t.strictEqual(res.statusCode, 200)
|
1854 | t.deepEqual(JSON.parse(res.payload), { hello: 'world' })
|
1855 | })
|
1856 | })
|
1857 |
|
1858 | test('onRequest, preHandler, and onResponse hooks that resolve to a value do not cause an error', t => {
|
1859 | t.plan(3)
|
1860 | const fastify = Fastify()
|
1861 |
|
1862 | fastify
|
1863 | .addHook('onRequest', () => Promise.resolve(1))
|
1864 | .addHook('onRequest', () => Promise.resolve(true))
|
1865 | .addHook('preValidation', () => Promise.resolve(null))
|
1866 | .addHook('preValidation', () => Promise.resolve('a'))
|
1867 | .addHook('preHandler', () => Promise.resolve(null))
|
1868 | .addHook('preHandler', () => Promise.resolve('a'))
|
1869 | .addHook('onResponse', () => Promise.resolve({}))
|
1870 | .addHook('onResponse', () => Promise.resolve([]))
|
1871 |
|
1872 | fastify.get('/', (request, reply) => {
|
1873 | reply.send('hello')
|
1874 | })
|
1875 |
|
1876 | fastify.inject('/', (err, res) => {
|
1877 | t.error(err)
|
1878 | t.strictEqual(res.statusCode, 200)
|
1879 | t.strictEqual(res.payload, 'hello')
|
1880 | })
|
1881 | })
|
1882 |
|
1883 | test('If a response header has been set inside an hook it shoulod not be overwritten by the final response handler', t => {
|
1884 | t.plan(5)
|
1885 | const fastify = Fastify()
|
1886 |
|
1887 | fastify.addHook('onRequest', (req, reply, next) => {
|
1888 | reply.header('X-Custom-Header', 'hello')
|
1889 | next()
|
1890 | })
|
1891 |
|
1892 | fastify.get('/', (request, reply) => {
|
1893 | reply.send('hello')
|
1894 | })
|
1895 |
|
1896 | fastify.inject('/', (err, res) => {
|
1897 | t.error(err)
|
1898 | t.strictEqual(res.headers['x-custom-header'], 'hello')
|
1899 | t.strictEqual(res.headers['content-type'], 'text/plain; charset=utf-8')
|
1900 | t.strictEqual(res.statusCode, 200)
|
1901 | t.strictEqual(res.payload, 'hello')
|
1902 | })
|
1903 | })
|
1904 |
|
1905 | test('If the content type has been set inside an hook it should not be changed', t => {
|
1906 | t.plan(5)
|
1907 | const fastify = Fastify()
|
1908 |
|
1909 | fastify.addHook('onRequest', (req, reply, next) => {
|
1910 | reply.header('content-type', 'text/html')
|
1911 | next()
|
1912 | })
|
1913 |
|
1914 | fastify.get('/', (request, reply) => {
|
1915 | t.ok(reply[symbols.kReplyHeaders]['content-type'])
|
1916 | reply.send('hello')
|
1917 | })
|
1918 |
|
1919 | fastify.inject('/', (err, res) => {
|
1920 | t.error(err)
|
1921 | t.strictEqual(res.headers['content-type'], 'text/html')
|
1922 | t.strictEqual(res.statusCode, 200)
|
1923 | t.strictEqual(res.payload, 'hello')
|
1924 | })
|
1925 | })
|
1926 |
|
1927 | test('request in onRequest, preParsing, preValidation and onResponse', t => {
|
1928 | t.plan(18)
|
1929 | const fastify = Fastify()
|
1930 |
|
1931 | fastify.addHook('onRequest', function (request, reply, next) {
|
1932 | t.deepEqual(request.body, null)
|
1933 | t.deepEqual(request.query, { key: 'value' })
|
1934 | t.deepEqual(request.params, { greeting: 'hello' })
|
1935 | t.deepEqual(request.headers, {
|
1936 | 'content-length': '17',
|
1937 | 'content-type': 'application/json',
|
1938 | host: 'localhost:80',
|
1939 | 'user-agent': 'lightMyRequest',
|
1940 | 'x-custom': 'hello'
|
1941 | })
|
1942 | next()
|
1943 | })
|
1944 |
|
1945 | fastify.addHook('preParsing', function (request, reply, next) {
|
1946 | t.deepEqual(request.body, null)
|
1947 | t.deepEqual(request.query, { key: 'value' })
|
1948 | t.deepEqual(request.params, { greeting: 'hello' })
|
1949 | t.deepEqual(request.headers, {
|
1950 | 'content-length': '17',
|
1951 | 'content-type': 'application/json',
|
1952 | host: 'localhost:80',
|
1953 | 'user-agent': 'lightMyRequest',
|
1954 | 'x-custom': 'hello'
|
1955 | })
|
1956 | next()
|
1957 | })
|
1958 |
|
1959 | fastify.addHook('preValidation', function (request, reply, next) {
|
1960 | t.deepEqual(request.body, { hello: 'world' })
|
1961 | t.deepEqual(request.query, { key: 'value' })
|
1962 | t.deepEqual(request.params, { greeting: 'hello' })
|
1963 | t.deepEqual(request.headers, {
|
1964 | 'content-length': '17',
|
1965 | 'content-type': 'application/json',
|
1966 | host: 'localhost:80',
|
1967 | 'user-agent': 'lightMyRequest',
|
1968 | 'x-custom': 'hello'
|
1969 | })
|
1970 | next()
|
1971 | })
|
1972 |
|
1973 | fastify.addHook('onResponse', function (request, reply, next) {
|
1974 | t.deepEqual(request.body, { hello: 'world' })
|
1975 | t.deepEqual(request.query, { key: 'value' })
|
1976 | t.deepEqual(request.params, { greeting: 'hello' })
|
1977 | t.deepEqual(request.headers, {
|
1978 | 'content-length': '17',
|
1979 | 'content-type': 'application/json',
|
1980 | host: 'localhost:80',
|
1981 | 'user-agent': 'lightMyRequest',
|
1982 | 'x-custom': 'hello'
|
1983 | })
|
1984 | next()
|
1985 | })
|
1986 |
|
1987 | fastify.post('/:greeting', function (req, reply) {
|
1988 | reply.send('ok')
|
1989 | })
|
1990 |
|
1991 | fastify.inject({
|
1992 | method: 'POST',
|
1993 | url: '/hello?key=value',
|
1994 | headers: { 'x-custom': 'hello' },
|
1995 | payload: { hello: 'world' }
|
1996 | }, (err, res) => {
|
1997 | t.error(err)
|
1998 | t.strictEqual(res.statusCode, 200)
|
1999 | })
|
2000 | })
|
2001 |
|
2002 | test('preValidation hook should support encapsulation / 1', t => {
|
2003 | t.plan(5)
|
2004 | const fastify = Fastify()
|
2005 |
|
2006 | fastify.register((instance, opts, next) => {
|
2007 | instance.addHook('preValidation', (req, reply, next) => {
|
2008 | t.strictEqual(req.raw.url, '/plugin')
|
2009 | next()
|
2010 | })
|
2011 |
|
2012 | instance.get('/plugin', (request, reply) => {
|
2013 | reply.send()
|
2014 | })
|
2015 |
|
2016 | next()
|
2017 | })
|
2018 |
|
2019 | fastify.get('/root', (request, reply) => {
|
2020 | reply.send()
|
2021 | })
|
2022 |
|
2023 | fastify.inject('/root', (err, res) => {
|
2024 | t.error(err)
|
2025 | t.strictEqual(res.statusCode, 200)
|
2026 | })
|
2027 |
|
2028 | fastify.inject('/plugin', (err, res) => {
|
2029 | t.error(err)
|
2030 | t.strictEqual(res.statusCode, 200)
|
2031 | })
|
2032 | })
|
2033 |
|
2034 | test('preValidation hook should support encapsulation / 2', t => {
|
2035 | t.plan(3)
|
2036 | const fastify = Fastify()
|
2037 | var pluginInstance
|
2038 |
|
2039 | fastify.addHook('preValidation', () => {})
|
2040 |
|
2041 | fastify.register((instance, opts, next) => {
|
2042 | instance.addHook('preValidation', () => {})
|
2043 | pluginInstance = instance
|
2044 | next()
|
2045 | })
|
2046 |
|
2047 | fastify.ready(err => {
|
2048 | t.error(err)
|
2049 | t.is(fastify[symbols.kHooks].preValidation.length, 1)
|
2050 | t.is(pluginInstance[symbols.kHooks].preValidation.length, 2)
|
2051 | })
|
2052 | })
|
2053 |
|
2054 | test('preValidation hook should support encapsulation / 3', t => {
|
2055 | t.plan(20)
|
2056 | const fastify = Fastify()
|
2057 | fastify.decorate('hello', 'world')
|
2058 |
|
2059 | fastify.addHook('preValidation', function (req, reply, next) {
|
2060 | t.ok(this.hello)
|
2061 | t.ok(this.hello2)
|
2062 | req.first = true
|
2063 | next()
|
2064 | })
|
2065 |
|
2066 | fastify.decorate('hello2', 'world')
|
2067 |
|
2068 | fastify.get('/first', (req, reply) => {
|
2069 | t.ok(req.first)
|
2070 | t.notOk(req.second)
|
2071 | reply.send({ hello: 'world' })
|
2072 | })
|
2073 |
|
2074 | fastify.register((instance, opts, next) => {
|
2075 | instance.decorate('hello3', 'world')
|
2076 | instance.addHook('preValidation', function (req, reply, next) {
|
2077 | t.ok(this.hello)
|
2078 | t.ok(this.hello2)
|
2079 | t.ok(this.hello3)
|
2080 | req.second = true
|
2081 | next()
|
2082 | })
|
2083 |
|
2084 | instance.get('/second', (req, reply) => {
|
2085 | t.ok(req.first)
|
2086 | t.ok(req.second)
|
2087 | reply.send({ hello: 'world' })
|
2088 | })
|
2089 |
|
2090 | next()
|
2091 | })
|
2092 |
|
2093 | fastify.listen(0, err => {
|
2094 | t.error(err)
|
2095 | fastify.server.unref()
|
2096 |
|
2097 | sget({
|
2098 | method: 'GET',
|
2099 | url: 'http://localhost:' + fastify.server.address().port + '/first'
|
2100 | }, (err, response, body) => {
|
2101 | t.error(err)
|
2102 | t.strictEqual(response.statusCode, 200)
|
2103 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
2104 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
2105 | })
|
2106 |
|
2107 | sget({
|
2108 | method: 'GET',
|
2109 | url: 'http://localhost:' + fastify.server.address().port + '/second'
|
2110 | }, (err, response, body) => {
|
2111 | t.error(err)
|
2112 | t.strictEqual(response.statusCode, 200)
|
2113 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
2114 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
2115 | })
|
2116 | })
|
2117 | })
|
2118 |
|
2119 | test('onError hook', t => {
|
2120 | t.plan(3)
|
2121 |
|
2122 | const fastify = Fastify()
|
2123 |
|
2124 | const err = new Error('kaboom')
|
2125 |
|
2126 | fastify.addHook('onError', (request, reply, error, next) => {
|
2127 | t.match(error, err)
|
2128 | next()
|
2129 | })
|
2130 |
|
2131 | fastify.get('/', (req, reply) => {
|
2132 | reply.send(err)
|
2133 | })
|
2134 |
|
2135 | fastify.inject({
|
2136 | method: 'GET',
|
2137 | url: '/'
|
2138 | }, (err, res) => {
|
2139 | t.error(err)
|
2140 | t.deepEqual(JSON.parse(res.payload), {
|
2141 | error: 'Internal Server Error',
|
2142 | message: 'kaboom',
|
2143 | statusCode: 500
|
2144 | })
|
2145 | })
|
2146 | })
|
2147 |
|
2148 | test('reply.send should throw if called inside the onError hook', t => {
|
2149 | t.plan(3)
|
2150 |
|
2151 | const fastify = Fastify()
|
2152 |
|
2153 | const err = new Error('kaboom')
|
2154 |
|
2155 | fastify.addHook('onError', (request, reply, error, next) => {
|
2156 | try {
|
2157 | reply.send()
|
2158 | t.fail('Should throw')
|
2159 | } catch (err) {
|
2160 | t.is(err.code, 'FST_ERR_SEND_INSIDE_ONERR')
|
2161 | }
|
2162 | next()
|
2163 | })
|
2164 |
|
2165 | fastify.get('/', (req, reply) => {
|
2166 | reply.send(err)
|
2167 | })
|
2168 |
|
2169 | fastify.inject({
|
2170 | method: 'GET',
|
2171 | url: '/'
|
2172 | }, (err, res) => {
|
2173 | t.error(err)
|
2174 | t.deepEqual(JSON.parse(res.payload), {
|
2175 | error: 'Internal Server Error',
|
2176 | message: 'kaboom',
|
2177 | statusCode: 500
|
2178 | })
|
2179 | })
|
2180 | })
|
2181 |
|
2182 | test('onError hook with setErrorHandler', t => {
|
2183 | t.test('Send error', t => {
|
2184 | t.plan(3)
|
2185 |
|
2186 | const fastify = Fastify()
|
2187 |
|
2188 | const err = new Error('ouch')
|
2189 |
|
2190 | fastify.setErrorHandler((_, req, reply) => {
|
2191 | reply.send(err)
|
2192 | })
|
2193 |
|
2194 | fastify.addHook('onError', (request, reply, error, next) => {
|
2195 | t.match(error, err)
|
2196 | next()
|
2197 | })
|
2198 |
|
2199 | fastify.get('/', (req, reply) => {
|
2200 | reply.send(new Error('kaboom'))
|
2201 | })
|
2202 |
|
2203 | fastify.inject({
|
2204 | method: 'GET',
|
2205 | url: '/'
|
2206 | }, (err, res) => {
|
2207 | t.error(err)
|
2208 | t.deepEqual(JSON.parse(res.payload), {
|
2209 | error: 'Internal Server Error',
|
2210 | message: 'ouch',
|
2211 | statusCode: 500
|
2212 | })
|
2213 | })
|
2214 | })
|
2215 |
|
2216 | t.test('Hide error', t => {
|
2217 | t.plan(2)
|
2218 |
|
2219 | const fastify = Fastify()
|
2220 |
|
2221 | fastify.setErrorHandler((_, req, reply) => {
|
2222 | reply.send({ hello: 'world' })
|
2223 | })
|
2224 |
|
2225 | fastify.addHook('onError', (request, reply, error, next) => {
|
2226 | t.fail('Should not be called')
|
2227 | })
|
2228 |
|
2229 | fastify.get('/', (req, reply) => {
|
2230 | reply.send(new Error('kaboom'))
|
2231 | })
|
2232 |
|
2233 | fastify.inject({
|
2234 | method: 'GET',
|
2235 | url: '/'
|
2236 | }, (err, res) => {
|
2237 | t.error(err)
|
2238 | t.deepEqual(
|
2239 | JSON.parse(res.payload),
|
2240 | { hello: 'world' }
|
2241 | )
|
2242 | })
|
2243 | })
|
2244 | t.end()
|
2245 | })
|
2246 |
|
2247 | test('preParsing hook should support encapsulation / 1', t => {
|
2248 | t.plan(5)
|
2249 | const fastify = Fastify()
|
2250 |
|
2251 | fastify.register((instance, opts, next) => {
|
2252 | instance.addHook('preParsing', (req, reply, next) => {
|
2253 | t.strictEqual(req.raw.url, '/plugin')
|
2254 | next()
|
2255 | })
|
2256 |
|
2257 | instance.get('/plugin', (request, reply) => {
|
2258 | reply.send()
|
2259 | })
|
2260 |
|
2261 | next()
|
2262 | })
|
2263 |
|
2264 | fastify.get('/root', (request, reply) => {
|
2265 | reply.send()
|
2266 | })
|
2267 |
|
2268 | fastify.inject('/root', (err, res) => {
|
2269 | t.error(err)
|
2270 | t.strictEqual(res.statusCode, 200)
|
2271 | })
|
2272 |
|
2273 | fastify.inject('/plugin', (err, res) => {
|
2274 | t.error(err)
|
2275 | t.strictEqual(res.statusCode, 200)
|
2276 | })
|
2277 | })
|
2278 |
|
2279 | test('preParsing hook should support encapsulation / 2', t => {
|
2280 | t.plan(3)
|
2281 | const fastify = Fastify()
|
2282 | var pluginInstance
|
2283 |
|
2284 | fastify.addHook('preParsing', function a () {})
|
2285 |
|
2286 | fastify.register((instance, opts, next) => {
|
2287 | instance.addHook('preParsing', function b () {})
|
2288 | pluginInstance = instance
|
2289 | next()
|
2290 | })
|
2291 |
|
2292 | fastify.ready(err => {
|
2293 | t.error(err)
|
2294 | t.is(fastify[symbols.kHooks].preParsing.length, 1)
|
2295 | t.is(pluginInstance[symbols.kHooks].preParsing.length, 2)
|
2296 | })
|
2297 | })
|
2298 |
|
2299 | test('preParsing hook should support encapsulation / 3', t => {
|
2300 | t.plan(20)
|
2301 | const fastify = Fastify()
|
2302 | fastify.decorate('hello', 'world')
|
2303 |
|
2304 | fastify.addHook('preParsing', function (req, reply, next) {
|
2305 | t.ok(this.hello)
|
2306 | t.ok(this.hello2)
|
2307 | req.first = true
|
2308 | next()
|
2309 | })
|
2310 |
|
2311 | fastify.decorate('hello2', 'world')
|
2312 |
|
2313 | fastify.get('/first', (req, reply) => {
|
2314 | t.ok(req.first)
|
2315 | t.notOk(req.second)
|
2316 | reply.send({ hello: 'world' })
|
2317 | })
|
2318 |
|
2319 | fastify.register((instance, opts, next) => {
|
2320 | instance.decorate('hello3', 'world')
|
2321 | instance.addHook('preParsing', function (req, reply, next) {
|
2322 | t.ok(this.hello)
|
2323 | t.ok(this.hello2)
|
2324 | t.ok(this.hello3)
|
2325 | req.second = true
|
2326 | next()
|
2327 | })
|
2328 |
|
2329 | instance.get('/second', (req, reply) => {
|
2330 | t.ok(req.first)
|
2331 | t.ok(req.second)
|
2332 | reply.send({ hello: 'world' })
|
2333 | })
|
2334 |
|
2335 | next()
|
2336 | })
|
2337 |
|
2338 | fastify.listen(0, err => {
|
2339 | t.error(err)
|
2340 | fastify.server.unref()
|
2341 |
|
2342 | sget({
|
2343 | method: 'GET',
|
2344 | url: 'http://localhost:' + fastify.server.address().port + '/first'
|
2345 | }, (err, response, body) => {
|
2346 | t.error(err)
|
2347 | t.strictEqual(response.statusCode, 200)
|
2348 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
2349 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
2350 | })
|
2351 |
|
2352 | sget({
|
2353 | method: 'GET',
|
2354 | url: 'http://localhost:' + fastify.server.address().port + '/second'
|
2355 | }, (err, response, body) => {
|
2356 | t.error(err)
|
2357 | t.strictEqual(response.statusCode, 200)
|
2358 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
2359 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
2360 | })
|
2361 | })
|
2362 | })
|
2363 |
|
2364 | test('preSerialization hook should run before serialization and be able to modify the payload', t => {
|
2365 | t.plan(5)
|
2366 | const fastify = Fastify()
|
2367 |
|
2368 | fastify.addHook('preSerialization', function (req, reply, payload, next) {
|
2369 | payload.hello += '1'
|
2370 | payload.world = 'ok'
|
2371 |
|
2372 | next(null, payload)
|
2373 | })
|
2374 |
|
2375 | fastify.route({
|
2376 | method: 'GET',
|
2377 | url: '/first',
|
2378 | handler: function (req, reply) {
|
2379 | reply.send({ hello: 'world' })
|
2380 | },
|
2381 | schema: {
|
2382 | response: {
|
2383 | 200: {
|
2384 | type: 'object',
|
2385 | properties: {
|
2386 | hello: {
|
2387 | type: 'string'
|
2388 | },
|
2389 | world: {
|
2390 | type: 'string'
|
2391 | }
|
2392 | },
|
2393 | required: ['world'],
|
2394 | additionalProperties: false
|
2395 | }
|
2396 | }
|
2397 | }
|
2398 | })
|
2399 |
|
2400 | fastify.listen(0, err => {
|
2401 | t.error(err)
|
2402 | fastify.server.unref()
|
2403 |
|
2404 | sget({
|
2405 | method: 'GET',
|
2406 | url: 'http://localhost:' + fastify.server.address().port + '/first'
|
2407 | }, (err, response, body) => {
|
2408 | t.error(err)
|
2409 | t.strictEqual(response.statusCode, 200)
|
2410 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
2411 | t.deepEqual(JSON.parse(body), { hello: 'world1', world: 'ok' })
|
2412 | })
|
2413 | })
|
2414 | })
|
2415 |
|
2416 | test('preSerialization hook should be able to throw errors which are not validated against schema response', t => {
|
2417 | const fastify = Fastify()
|
2418 |
|
2419 | fastify.addHook('preSerialization', function (req, reply, payload, next) {
|
2420 | next(new Error('preSerialization aborted'))
|
2421 | })
|
2422 |
|
2423 | fastify.route({
|
2424 | method: 'GET',
|
2425 | url: '/first',
|
2426 | handler: function (req, reply) {
|
2427 | reply.send({ hello: 'world' })
|
2428 | },
|
2429 | schema: {
|
2430 | response: {
|
2431 | 500: {
|
2432 | type: 'object',
|
2433 | properties: {
|
2434 | world: {
|
2435 | type: 'string'
|
2436 | }
|
2437 | },
|
2438 | required: ['world'],
|
2439 | additionalProperties: false
|
2440 | }
|
2441 | }
|
2442 | }
|
2443 | })
|
2444 |
|
2445 | fastify.listen(0, err => {
|
2446 | t.error(err)
|
2447 | fastify.server.unref()
|
2448 |
|
2449 | sget({
|
2450 | method: 'GET',
|
2451 | url: 'http://localhost:' + fastify.server.address().port + '/first'
|
2452 | }, (err, response, body) => {
|
2453 | t.error(err)
|
2454 | t.strictEqual(response.statusCode, 500)
|
2455 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
2456 | t.deepEqual(JSON.parse(body), { error: 'Internal Server Error', message: 'preSerialization aborted', statusCode: 500 })
|
2457 | t.end()
|
2458 | })
|
2459 | })
|
2460 | })
|
2461 |
|
2462 | test('preSerialization hook which returned error should still run onError hooks', t => {
|
2463 | t.plan(4)
|
2464 | const fastify = Fastify()
|
2465 |
|
2466 | fastify.addHook('preSerialization', function (req, reply, payload, next) {
|
2467 | next(new Error('preSerialization aborted'))
|
2468 | })
|
2469 |
|
2470 | fastify.addHook('onError', function (req, reply, payload, next) {
|
2471 | t.pass()
|
2472 | next()
|
2473 | })
|
2474 |
|
2475 | fastify.get('/first', (req, reply) => {
|
2476 | reply.send({ hello: 'world' })
|
2477 | })
|
2478 |
|
2479 | fastify.listen(0, err => {
|
2480 | t.error(err)
|
2481 | fastify.server.unref()
|
2482 |
|
2483 | sget({
|
2484 | method: 'GET',
|
2485 | url: 'http://localhost:' + fastify.server.address().port + '/first'
|
2486 | }, (err, response, body) => {
|
2487 | t.error(err)
|
2488 | t.strictEqual(response.statusCode, 500)
|
2489 | })
|
2490 | })
|
2491 | })
|
2492 |
|
2493 | test('preSerialization hooks should run in the order in which they are defined', t => {
|
2494 | t.plan(5)
|
2495 | const fastify = Fastify()
|
2496 |
|
2497 | fastify.addHook('preSerialization', function (req, reply, payload, next) {
|
2498 | payload.hello += '2'
|
2499 |
|
2500 | next(null, payload)
|
2501 | })
|
2502 |
|
2503 | fastify.addHook('preSerialization', function (req, reply, payload, next) {
|
2504 | payload.hello += '1'
|
2505 |
|
2506 | next(null, payload)
|
2507 | })
|
2508 |
|
2509 | fastify.get('/first', (req, reply) => {
|
2510 | reply.send(payload)
|
2511 | })
|
2512 |
|
2513 | fastify.listen(0, err => {
|
2514 | t.error(err)
|
2515 | fastify.server.unref()
|
2516 |
|
2517 | sget({
|
2518 | method: 'GET',
|
2519 | url: 'http://localhost:' + fastify.server.address().port + '/first'
|
2520 | }, (err, response, body) => {
|
2521 | t.error(err)
|
2522 | t.strictEqual(response.statusCode, 200)
|
2523 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
2524 | t.deepEqual(JSON.parse(body), { hello: 'world21' })
|
2525 | })
|
2526 | })
|
2527 | })
|
2528 |
|
2529 | test('preSerialization hooks should support encapsulation', t => {
|
2530 | t.plan(9)
|
2531 | const fastify = Fastify()
|
2532 |
|
2533 | fastify.addHook('preSerialization', function (req, reply, payload, next) {
|
2534 | payload.hello += '1'
|
2535 |
|
2536 | next(null, payload)
|
2537 | })
|
2538 |
|
2539 | fastify.get('/first', (req, reply) => {
|
2540 | reply.send({ hello: 'world' })
|
2541 | })
|
2542 |
|
2543 | fastify.register((instance, opts, next) => {
|
2544 | instance.addHook('preSerialization', function (req, reply, payload, next) {
|
2545 | payload.hello += '2'
|
2546 |
|
2547 | next(null, payload)
|
2548 | })
|
2549 |
|
2550 | instance.get('/second', (req, reply) => {
|
2551 | reply.send({ hello: 'world' })
|
2552 | })
|
2553 |
|
2554 | next()
|
2555 | })
|
2556 |
|
2557 | fastify.listen(0, err => {
|
2558 | t.error(err)
|
2559 | fastify.server.unref()
|
2560 |
|
2561 | sget({
|
2562 | method: 'GET',
|
2563 | url: 'http://localhost:' + fastify.server.address().port + '/first'
|
2564 | }, (err, response, body) => {
|
2565 | t.error(err)
|
2566 | t.strictEqual(response.statusCode, 200)
|
2567 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
2568 | t.deepEqual(JSON.parse(body), { hello: 'world1' })
|
2569 | })
|
2570 |
|
2571 | sget({
|
2572 | method: 'GET',
|
2573 | url: 'http://localhost:' + fastify.server.address().port + '/second'
|
2574 | }, (err, response, body) => {
|
2575 | t.error(err)
|
2576 | t.strictEqual(response.statusCode, 200)
|
2577 | t.strictEqual(response.headers['content-length'], '' + body.length)
|
2578 | t.deepEqual(JSON.parse(body), { hello: 'world12' })
|
2579 | })
|
2580 | })
|
2581 | })
|
2582 |
|
2583 | test('onRegister hook should be called / 1', t => {
|
2584 | t.plan(3)
|
2585 | const fastify = Fastify()
|
2586 |
|
2587 | fastify.register((instance, opts, next) => {
|
2588 | next()
|
2589 | })
|
2590 |
|
2591 | fastify.addHook('onRegister', instance => {
|
2592 |
|
2593 | t.ok(instance.addHook)
|
2594 | })
|
2595 |
|
2596 | fastify.ready(err => {
|
2597 | t.error(err)
|
2598 | })
|
2599 | })
|
2600 |
|
2601 | test('onRegister hook should be called / 2', t => {
|
2602 | t.plan(5)
|
2603 | const fastify = Fastify()
|
2604 |
|
2605 | fastify.register((instance, opts, next) => {
|
2606 | instance.register((instance, opts, next) => {
|
2607 | next()
|
2608 | })
|
2609 | next()
|
2610 | })
|
2611 |
|
2612 | fastify.register((instance, opts, next) => {
|
2613 | next()
|
2614 | })
|
2615 |
|
2616 | fastify.addHook('onRegister', instance => {
|
2617 |
|
2618 | t.ok(instance.addHook)
|
2619 | })
|
2620 |
|
2621 | fastify.ready(err => {
|
2622 | t.error(err)
|
2623 | })
|
2624 | })
|
2625 |
|
2626 | test('onRegister hook should be called / 3', t => {
|
2627 | t.plan(4)
|
2628 | const fastify = Fastify()
|
2629 |
|
2630 | fastify.decorate('data', [])
|
2631 |
|
2632 | fastify.register((instance, opts, next) => {
|
2633 | instance.data.push(1)
|
2634 | instance.register((instance, opts, next) => {
|
2635 | instance.data.push(2)
|
2636 | t.deepEqual(instance.data, [1, 2])
|
2637 | next()
|
2638 | })
|
2639 | t.deepEqual(instance.data, [1])
|
2640 | next()
|
2641 | })
|
2642 |
|
2643 | fastify.register((instance, opts, next) => {
|
2644 | t.deepEqual(instance.data, [])
|
2645 | next()
|
2646 | })
|
2647 |
|
2648 | fastify.addHook('onRegister', instance => {
|
2649 | instance.data = instance.data.slice()
|
2650 | })
|
2651 |
|
2652 | fastify.ready(err => {
|
2653 | t.error(err)
|
2654 | })
|
2655 | })
|
2656 |
|
2657 | test('onRegister hook should be called / 4', t => {
|
2658 | t.plan(2)
|
2659 | const fastify = Fastify()
|
2660 |
|
2661 | function plugin (instance, opts, next) {
|
2662 | next()
|
2663 | }
|
2664 | plugin[Symbol.for('skip-override')] = true
|
2665 |
|
2666 | fastify.register(plugin)
|
2667 |
|
2668 | fastify.addHook('onRegister', instance => {
|
2669 |
|
2670 | t.ok(instance.addHook)
|
2671 | })
|
2672 |
|
2673 | fastify.ready(err => {
|
2674 | t.error(err)
|
2675 | })
|
2676 | })
|
2677 |
|
2678 | if (semver.gt(process.versions.node, '8.0.0')) {
|
2679 | require('./hooks-async')(t)
|
2680 | } else {
|
2681 | t.pass('Skip because Node version < 8')
|
2682 | t.end()
|
2683 | }
|