You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
448 lines
9.9 KiB
448 lines
9.9 KiB
4 years ago
|
'use strict'
|
||
|
|
||
|
const test = require('tap').test
|
||
|
const Fastify = require('../')
|
||
|
|
||
|
function endMiddleware (nextOrPayload, next) {
|
||
|
if (typeof nextOrPayload === 'function') {
|
||
|
nextOrPayload()
|
||
|
} else {
|
||
|
next()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function testExecutionHook (hook) {
|
||
|
test(`${hook}`, t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.post('/', {
|
||
|
[hook]: (req, reply, nextOrPayload, next) => {
|
||
|
t.pass('hook called')
|
||
|
endMiddleware(nextOrPayload, next)
|
||
|
}
|
||
|
}, (req, reply) => {
|
||
|
reply.send(req.body)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'POST',
|
||
|
url: '/',
|
||
|
payload: { hello: 'world' }
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
var payload = JSON.parse(res.payload)
|
||
|
t.deepEqual(payload, { hello: 'world' })
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test(`${hook} option should be called after ${hook} hook`, t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
const checker = Object.defineProperty({ calledTimes: 0 }, 'check', {
|
||
|
get: function () { return ++this.calledTimes }
|
||
|
})
|
||
|
|
||
|
fastify.addHook(hook, (req, reply, nextOrPayload, next) => {
|
||
|
t.equal(checker.check, 1)
|
||
|
endMiddleware(nextOrPayload, next)
|
||
|
})
|
||
|
|
||
|
fastify.post('/', {
|
||
|
[hook]: (req, reply, nextOrPayload, next) => {
|
||
|
t.equal(checker.check, 2)
|
||
|
endMiddleware(nextOrPayload, next)
|
||
|
}
|
||
|
}, (req, reply) => {
|
||
|
reply.send({})
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'POST',
|
||
|
url: '/',
|
||
|
payload: { hello: 'world' }
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test(`${hook} option could accept an array of functions`, t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
const checker = Object.defineProperty({ calledTimes: 0 }, 'check', {
|
||
|
get: function () { return ++this.calledTimes }
|
||
|
})
|
||
|
|
||
|
fastify.post('/', {
|
||
|
[hook]: [
|
||
|
(req, reply, nextOrPayload, next) => {
|
||
|
t.equal(checker.check, 1)
|
||
|
endMiddleware(nextOrPayload, next)
|
||
|
},
|
||
|
(req, reply, nextOrPayload, next) => {
|
||
|
t.equal(checker.check, 2)
|
||
|
endMiddleware(nextOrPayload, next)
|
||
|
}
|
||
|
]
|
||
|
}, (req, reply) => {
|
||
|
reply.send({})
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'POST',
|
||
|
url: '/',
|
||
|
payload: { hello: 'world' }
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test(`${hook} option does not interfere with ${hook} hook`, t => {
|
||
|
t.plan(7)
|
||
|
const fastify = Fastify()
|
||
|
const checker = Object.defineProperty({ calledTimes: 0 }, 'check', {
|
||
|
get: function () { return ++this.calledTimes }
|
||
|
})
|
||
|
|
||
|
fastify.addHook(hook, (req, reply, nextOrPayload, next) => {
|
||
|
t.equal(checker.check, 1)
|
||
|
endMiddleware(nextOrPayload, next)
|
||
|
})
|
||
|
|
||
|
fastify.post('/', {
|
||
|
[hook]: (req, reply, nextOrPayload, next) => {
|
||
|
t.equal(checker.check, 2)
|
||
|
endMiddleware(nextOrPayload, next)
|
||
|
}
|
||
|
}, handler)
|
||
|
|
||
|
fastify.post('/no', handler)
|
||
|
|
||
|
function handler (req, reply) {
|
||
|
reply.send({})
|
||
|
}
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'post',
|
||
|
url: '/'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(checker.calledTimes, 2)
|
||
|
|
||
|
checker.calledTimes = 0
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'post',
|
||
|
url: '/no'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(checker.calledTimes, 1)
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
|
||
|
function testBeforeHandlerHook (hook) {
|
||
|
test(`${hook} option should be unique per route`, t => {
|
||
|
t.plan(4)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.post('/', {
|
||
|
[hook]: (req, reply, done) => {
|
||
|
req.hello = 'earth'
|
||
|
done()
|
||
|
}
|
||
|
}, (req, reply) => {
|
||
|
reply.send({ hello: req.hello })
|
||
|
})
|
||
|
|
||
|
fastify.post('/no', (req, reply) => {
|
||
|
reply.send(req.body)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'POST',
|
||
|
url: '/',
|
||
|
payload: { hello: 'world' }
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
var payload = JSON.parse(res.payload)
|
||
|
t.deepEqual(payload, { hello: 'earth' })
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'POST',
|
||
|
url: '/no',
|
||
|
payload: { hello: 'world' }
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
var payload = JSON.parse(res.payload)
|
||
|
t.deepEqual(payload, { hello: 'world' })
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test(`${hook} option should handle errors`, t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.post('/', {
|
||
|
[hook]: (req, reply, done) => {
|
||
|
done(new Error('kaboom'))
|
||
|
}
|
||
|
}, (req, reply) => {
|
||
|
reply.send(req.body)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'POST',
|
||
|
url: '/',
|
||
|
payload: { hello: 'world' }
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
var payload = JSON.parse(res.payload)
|
||
|
t.equal(res.statusCode, 500)
|
||
|
t.deepEqual(payload, {
|
||
|
message: 'kaboom',
|
||
|
error: 'Internal Server Error',
|
||
|
statusCode: 500
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test(`${hook} option should handle errors with custom status code`, t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.post('/', {
|
||
|
[hook]: (req, reply, done) => {
|
||
|
reply.code(401)
|
||
|
done(new Error('go away'))
|
||
|
}
|
||
|
}, (req, reply) => {
|
||
|
reply.send(req.body)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'POST',
|
||
|
url: '/',
|
||
|
payload: { hello: 'world' }
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
var payload = JSON.parse(res.payload)
|
||
|
t.equal(res.statusCode, 401)
|
||
|
t.deepEqual(payload, {
|
||
|
message: 'go away',
|
||
|
error: 'Unauthorized',
|
||
|
statusCode: 401
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test(`${hook} option should keep the context`, t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.decorate('foo', 42)
|
||
|
|
||
|
fastify.post('/', {
|
||
|
[hook]: function (req, reply, done) {
|
||
|
t.strictEqual(this.foo, 42)
|
||
|
this.foo += 1
|
||
|
done()
|
||
|
}
|
||
|
}, function (req, reply) {
|
||
|
reply.send({ foo: this.foo })
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'POST',
|
||
|
url: '/',
|
||
|
payload: { hello: 'world' }
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
var payload = JSON.parse(res.payload)
|
||
|
t.deepEqual(payload, { foo: 43 })
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test(`${hook} option should keep the context (array)`, t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.decorate('foo', 42)
|
||
|
|
||
|
fastify.post('/', {
|
||
|
[hook]: [function (req, reply, done) {
|
||
|
t.strictEqual(this.foo, 42)
|
||
|
this.foo += 1
|
||
|
done()
|
||
|
}]
|
||
|
}, function (req, reply) {
|
||
|
reply.send({ foo: this.foo })
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'POST',
|
||
|
url: '/',
|
||
|
payload: { hello: 'world' }
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
var payload = JSON.parse(res.payload)
|
||
|
t.deepEqual(payload, { foo: 43 })
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
|
||
|
testExecutionHook('preHandler')
|
||
|
testExecutionHook('onSend')
|
||
|
testExecutionHook('onRequest')
|
||
|
testExecutionHook('onResponse')
|
||
|
testExecutionHook('preValidation')
|
||
|
testExecutionHook('preParsing')
|
||
|
// hooks that comes before the handler
|
||
|
testBeforeHandlerHook('preHandler')
|
||
|
testBeforeHandlerHook('onRequest')
|
||
|
testBeforeHandlerHook('preValidation')
|
||
|
testBeforeHandlerHook('preParsing')
|
||
|
|
||
|
test('preHandler backwards compatibility with beforeHandler option (should emit a warning)', t => {
|
||
|
t.plan(4)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
process.on('warning', warn => {
|
||
|
t.strictEqual(
|
||
|
warn.message,
|
||
|
'The route option `beforeHandler` has been deprecated, use `preHandler` instead'
|
||
|
)
|
||
|
t.ok(warn.stack.indexOf(__filename) >= 0)
|
||
|
})
|
||
|
|
||
|
fastify.post('/', {
|
||
|
beforeHandler: (req, reply, done) => {
|
||
|
req.body.preHandler = true
|
||
|
done()
|
||
|
}
|
||
|
}, (req, reply) => {
|
||
|
reply.send(req.body)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'POST',
|
||
|
url: '/',
|
||
|
payload: { hello: 'world' }
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
var payload = JSON.parse(res.payload)
|
||
|
t.deepEqual(payload, { preHandler: true, hello: 'world' })
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('preValidation option should be called before preHandler hook', t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.addHook('preHandler', (req, reply, next) => {
|
||
|
t.true(req.called)
|
||
|
next()
|
||
|
})
|
||
|
|
||
|
fastify.post('/', {
|
||
|
preValidation: (req, reply, done) => {
|
||
|
req.called = true
|
||
|
done()
|
||
|
}
|
||
|
}, (req, reply) => {
|
||
|
reply.send(req.body)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'POST',
|
||
|
url: '/',
|
||
|
payload: { hello: 'world' }
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
var payload = JSON.parse(res.payload)
|
||
|
t.deepEqual(payload, { hello: 'world' })
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('preSerialization option should be able to modify the payload', t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.get('/only', {
|
||
|
preSerialization: (req, reply, payload, done) => {
|
||
|
done(null, { hello: 'another world' })
|
||
|
}
|
||
|
}, (req, reply) => {
|
||
|
reply.send({ hello: 'world' })
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/only'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(res.statusCode, 200)
|
||
|
t.deepEqual(JSON.parse(res.payload), { hello: 'another world' })
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('preParsing option should be called before preValidation hook', t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.addHook('preValidation', (req, reply, next) => {
|
||
|
t.true(req.called)
|
||
|
next()
|
||
|
})
|
||
|
|
||
|
fastify.post('/', {
|
||
|
preParsing: (req, reply, done) => {
|
||
|
req.called = true
|
||
|
done()
|
||
|
}
|
||
|
}, (req, reply) => {
|
||
|
reply.send(req.body)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'POST',
|
||
|
url: '/',
|
||
|
payload: { hello: 'world' }
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
var payload = JSON.parse(res.payload)
|
||
|
t.deepEqual(payload, { hello: 'world' })
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('onRequest option should be called before preParsing', t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.addHook('preParsing', (req, reply, next) => {
|
||
|
t.true(req.called)
|
||
|
next()
|
||
|
})
|
||
|
|
||
|
fastify.post('/', {
|
||
|
onRequest: (req, reply, done) => {
|
||
|
req.called = true
|
||
|
done()
|
||
|
}
|
||
|
}, (req, reply) => {
|
||
|
reply.send(req.body)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'POST',
|
||
|
url: '/',
|
||
|
payload: { hello: 'world' }
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
var payload = JSON.parse(res.payload)
|
||
|
t.deepEqual(payload, { hello: 'world' })
|
||
|
})
|
||
|
})
|