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.
		
		
		
		
		
			
		
			
				
					
					
						
							1851 lines
						
					
					
						
							43 KiB
						
					
					
				
			
		
		
	
	
							1851 lines
						
					
					
						
							43 KiB
						
					
					
				| 'use strict'
 | |
| 
 | |
| const t = require('tap')
 | |
| const test = t.test
 | |
| const fp = require('fastify-plugin')
 | |
| const httpErrors = require('http-errors')
 | |
| const sget = require('simple-get').concat
 | |
| const errors = require('http-errors')
 | |
| const split = require('split2')
 | |
| const Fastify = require('..')
 | |
| 
 | |
| test('default 404', t => {
 | |
|   t.plan(3)
 | |
| 
 | |
|   const test = t.test
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.error(err)
 | |
| 
 | |
|     test('unsupported method', t => {
 | |
|       t.plan(3)
 | |
|       sget({
 | |
|         method: 'PUT',
 | |
|         url: 'http://localhost:' + fastify.server.address().port,
 | |
|         body: {},
 | |
|         json: true
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(response.headers['content-type'], 'application/json; charset=utf-8')
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     test('unsupported route', t => {
 | |
|       t.plan(3)
 | |
|       sget({
 | |
|         method: 'GET',
 | |
|         url: 'http://localhost:' + fastify.server.address().port + '/notSupported',
 | |
|         body: {},
 | |
|         json: true
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(response.headers['content-type'], 'application/json; charset=utf-8')
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('customized 404', t => {
 | |
|   t.plan(5)
 | |
| 
 | |
|   const test = t.test
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   fastify.get('/with-error', function (req, reply) {
 | |
|     reply.send(new errors.NotFound())
 | |
|   })
 | |
| 
 | |
|   fastify.get('/with-error-custom-header', function (req, reply) {
 | |
|     const err = new errors.NotFound()
 | |
|     err.headers = { 'x-foo': 'bar' }
 | |
|     reply.send(err)
 | |
|   })
 | |
| 
 | |
|   fastify.setNotFoundHandler(function (req, reply) {
 | |
|     reply.code(404).send('this was not found')
 | |
|   })
 | |
| 
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.error(err)
 | |
| 
 | |
|     test('unsupported method', t => {
 | |
|       t.plan(3)
 | |
|       sget({
 | |
|         method: 'PUT',
 | |
|         url: 'http://localhost:' + fastify.server.address().port,
 | |
|         body: JSON.stringify({ hello: 'world' }),
 | |
|         headers: { 'Content-Type': 'application/json' }
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(body.toString(), 'this was not found')
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     test('unsupported route', t => {
 | |
|       t.plan(3)
 | |
|       sget({
 | |
|         method: 'GET',
 | |
|         url: 'http://localhost:' + fastify.server.address().port + '/notSupported'
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(body.toString(), 'this was not found')
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     test('with error object', t => {
 | |
|       t.plan(3)
 | |
|       sget({
 | |
|         method: 'GET',
 | |
|         url: 'http://localhost:' + fastify.server.address().port + '/with-error'
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.same(JSON.parse(body), {
 | |
|           error: 'Not Found',
 | |
|           message: 'Not Found',
 | |
|           statusCode: 404
 | |
|         })
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     test('error object with headers property', t => {
 | |
|       t.plan(4)
 | |
|       sget({
 | |
|         method: 'GET',
 | |
|         url: 'http://localhost:' + fastify.server.address().port + '/with-error-custom-header'
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(response.headers['x-foo'], 'bar')
 | |
|         t.same(JSON.parse(body), {
 | |
|           error: 'Not Found',
 | |
|           message: 'Not Found',
 | |
|           statusCode: 404
 | |
|         })
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('custom header in notFound handler', t => {
 | |
|   t.plan(2)
 | |
| 
 | |
|   const test = t.test
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.setNotFoundHandler(function (req, reply) {
 | |
|     reply.code(404).header('x-foo', 'bar').send('this was not found')
 | |
|   })
 | |
| 
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.error(err)
 | |
| 
 | |
|     test('not found with custom header', t => {
 | |
|       t.plan(4)
 | |
|       sget({
 | |
|         method: 'GET',
 | |
|         url: 'http://localhost:' + fastify.server.address().port + '/notSupported'
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(response.headers['x-foo'], 'bar')
 | |
|         t.equal(body.toString(), 'this was not found')
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('setting a custom 404 handler multiple times is an error', t => {
 | |
|   t.plan(5)
 | |
| 
 | |
|   t.test('at the root level', t => {
 | |
|     t.plan(2)
 | |
| 
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.setNotFoundHandler(() => {})
 | |
| 
 | |
|     try {
 | |
|       fastify.setNotFoundHandler(() => {})
 | |
|       t.fail('setting multiple 404 handlers at the same prefix encapsulation level should throw')
 | |
|     } catch (err) {
 | |
|       t.type(err, Error)
 | |
|       t.equal(err.message, 'Not found handler already set for Fastify instance with prefix: \'/\'')
 | |
|     }
 | |
|   })
 | |
| 
 | |
|   t.test('at the plugin level', t => {
 | |
|     t.plan(3)
 | |
| 
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.register((instance, options, done) => {
 | |
|       instance.setNotFoundHandler(() => {})
 | |
| 
 | |
|       try {
 | |
|         instance.setNotFoundHandler(() => {})
 | |
|         t.fail('setting multiple 404 handlers at the same prefix encapsulation level should throw')
 | |
|       } catch (err) {
 | |
|         t.type(err, Error)
 | |
|         t.equal(err.message, 'Not found handler already set for Fastify instance with prefix: \'/prefix\'')
 | |
|       }
 | |
| 
 | |
|       done()
 | |
|     }, { prefix: '/prefix' })
 | |
| 
 | |
|     fastify.listen(0, err => {
 | |
|       t.error(err)
 | |
|       fastify.close()
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('at multiple levels', t => {
 | |
|     t.plan(3)
 | |
| 
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.register((instance, options, done) => {
 | |
|       try {
 | |
|         instance.setNotFoundHandler(() => {})
 | |
|         t.fail('setting multiple 404 handlers at the same prefix encapsulation level should throw')
 | |
|       } catch (err) {
 | |
|         t.type(err, Error)
 | |
|         t.equal(err.message, 'Not found handler already set for Fastify instance with prefix: \'/\'')
 | |
|       }
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     fastify.setNotFoundHandler(() => {})
 | |
| 
 | |
|     fastify.listen(0, err => {
 | |
|       t.error(err)
 | |
|       fastify.close()
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('at multiple levels / 2', t => {
 | |
|     t.plan(3)
 | |
| 
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.register((instance, options, done) => {
 | |
|       instance.setNotFoundHandler(() => {})
 | |
| 
 | |
|       instance.register((instance2, options, done) => {
 | |
|         try {
 | |
|           instance2.setNotFoundHandler(() => {})
 | |
|           t.fail('setting multiple 404 handlers at the same prefix encapsulation level should throw')
 | |
|         } catch (err) {
 | |
|           t.type(err, Error)
 | |
|           t.equal(err.message, 'Not found handler already set for Fastify instance with prefix: \'/prefix\'')
 | |
|         }
 | |
|         done()
 | |
|       })
 | |
| 
 | |
|       done()
 | |
|     }, { prefix: '/prefix' })
 | |
| 
 | |
|     fastify.setNotFoundHandler(() => {})
 | |
| 
 | |
|     fastify.listen(0, err => {
 | |
|       t.error(err)
 | |
|       fastify.close()
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('in separate plugins at the same level', t => {
 | |
|     t.plan(3)
 | |
| 
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.register((instance, options, done) => {
 | |
|       instance.register((instance2A, options, done) => {
 | |
|         instance2A.setNotFoundHandler(() => {})
 | |
|         done()
 | |
|       })
 | |
| 
 | |
|       instance.register((instance2B, options, done) => {
 | |
|         try {
 | |
|           instance2B.setNotFoundHandler(() => {})
 | |
|           t.fail('setting multiple 404 handlers at the same prefix encapsulation level should throw')
 | |
|         } catch (err) {
 | |
|           t.type(err, Error)
 | |
|           t.equal(err.message, 'Not found handler already set for Fastify instance with prefix: \'/prefix\'')
 | |
|         }
 | |
|         done()
 | |
|       })
 | |
| 
 | |
|       done()
 | |
|     }, { prefix: '/prefix' })
 | |
| 
 | |
|     fastify.setNotFoundHandler(() => {})
 | |
| 
 | |
|     fastify.listen(0, err => {
 | |
|       t.error(err)
 | |
|       fastify.close()
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('encapsulated 404', t => {
 | |
|   t.plan(9)
 | |
| 
 | |
|   const test = t.test
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   fastify.setNotFoundHandler(function (req, reply) {
 | |
|     reply.code(404).send('this was not found')
 | |
|   })
 | |
| 
 | |
|   fastify.register(function (f, opts, done) {
 | |
|     f.setNotFoundHandler(function (req, reply) {
 | |
|       reply.code(404).send('this was not found 2')
 | |
|     })
 | |
|     done()
 | |
|   }, { prefix: '/test' })
 | |
| 
 | |
|   fastify.register(function (f, opts, done) {
 | |
|     f.setNotFoundHandler(function (req, reply) {
 | |
|       reply.code(404).send('this was not found 3')
 | |
|     })
 | |
|     done()
 | |
|   }, { prefix: '/test2' })
 | |
| 
 | |
|   fastify.register(function (f, opts, done) {
 | |
|     f.setNotFoundHandler(function (request, reply) {
 | |
|       reply.code(404).send('this was not found 4')
 | |
|     })
 | |
|     done()
 | |
|   }, { prefix: '/test3/' })
 | |
| 
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.error(err)
 | |
| 
 | |
|     test('root unsupported method', t => {
 | |
|       t.plan(3)
 | |
|       sget({
 | |
|         method: 'PUT',
 | |
|         url: 'http://localhost:' + fastify.server.address().port,
 | |
|         body: JSON.stringify({ hello: 'world' }),
 | |
|         headers: { 'Content-Type': 'application/json' }
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(body.toString(), 'this was not found')
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     test('root insupported route', t => {
 | |
|       t.plan(3)
 | |
|       sget({
 | |
|         method: 'GET',
 | |
|         url: 'http://localhost:' + fastify.server.address().port + '/notSupported'
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(body.toString(), 'this was not found')
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     test('unsupported method', t => {
 | |
|       t.plan(3)
 | |
|       sget({
 | |
|         method: 'PUT',
 | |
|         url: 'http://localhost:' + fastify.server.address().port + '/test',
 | |
|         body: JSON.stringify({ hello: 'world' }),
 | |
|         headers: { 'Content-Type': 'application/json' }
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(body.toString(), 'this was not found 2')
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     test('unsupported route', t => {
 | |
|       t.plan(3)
 | |
|       sget({
 | |
|         method: 'GET',
 | |
|         url: 'http://localhost:' + fastify.server.address().port + '/test/notSupported'
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(body.toString(), 'this was not found 2')
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     test('unsupported method bis', t => {
 | |
|       t.plan(3)
 | |
|       sget({
 | |
|         method: 'PUT',
 | |
|         url: 'http://localhost:' + fastify.server.address().port + '/test2',
 | |
|         body: JSON.stringify({ hello: 'world' }),
 | |
|         headers: { 'Content-Type': 'application/json' }
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(body.toString(), 'this was not found 3')
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     test('unsupported route bis', t => {
 | |
|       t.plan(3)
 | |
|       sget({
 | |
|         method: 'GET',
 | |
|         url: 'http://localhost:' + fastify.server.address().port + '/test2/notSupported'
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(body.toString(), 'this was not found 3')
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     test('unsupported method 3', t => {
 | |
|       t.plan(3)
 | |
|       sget({
 | |
|         method: 'PUT',
 | |
|         url: 'http://localhost:' + fastify.server.address().port + '/test3/',
 | |
|         body: JSON.stringify({ hello: 'world' }),
 | |
|         headers: { 'Content-Type': 'application/json' }
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(body.toString(), 'this was not found 4')
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     test('unsupported route 3', t => {
 | |
|       t.plan(3)
 | |
|       sget({
 | |
|         method: 'GET',
 | |
|         url: 'http://localhost:' + fastify.server.address().port + '/test3/notSupported'
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|         t.equal(body.toString(), 'this was not found 4')
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('custom 404 hook and handler context', t => {
 | |
|   t.plan(21)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.decorate('foo', 42)
 | |
| 
 | |
|   fastify.addHook('onRequest', function (req, res, done) {
 | |
|     t.equal(this.foo, 42)
 | |
|     done()
 | |
|   })
 | |
|   fastify.addHook('preHandler', function (request, reply, done) {
 | |
|     t.equal(this.foo, 42)
 | |
|     done()
 | |
|   })
 | |
|   fastify.addHook('onSend', function (request, reply, payload, done) {
 | |
|     t.equal(this.foo, 42)
 | |
|     done()
 | |
|   })
 | |
|   fastify.addHook('onResponse', function (request, reply, done) {
 | |
|     t.equal(this.foo, 42)
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   fastify.setNotFoundHandler(function (req, reply) {
 | |
|     t.equal(this.foo, 42)
 | |
|     reply.code(404).send('this was not found')
 | |
|   })
 | |
| 
 | |
|   fastify.register(function (instance, opts, done) {
 | |
|     instance.decorate('bar', 84)
 | |
| 
 | |
|     instance.addHook('onRequest', function (req, res, done) {
 | |
|       t.equal(this.bar, 84)
 | |
|       done()
 | |
|     })
 | |
|     instance.addHook('preHandler', function (request, reply, done) {
 | |
|       t.equal(this.bar, 84)
 | |
|       done()
 | |
|     })
 | |
|     instance.addHook('onSend', function (request, reply, payload, done) {
 | |
|       t.equal(this.bar, 84)
 | |
|       done()
 | |
|     })
 | |
|     instance.addHook('onResponse', function (request, reply, done) {
 | |
|       t.equal(this.bar, 84)
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     instance.setNotFoundHandler(function (req, reply) {
 | |
|       t.equal(this.foo, 42)
 | |
|       t.equal(this.bar, 84)
 | |
|       reply.code(404).send('encapsulated was not found')
 | |
|     })
 | |
| 
 | |
|     done()
 | |
|   }, { prefix: '/encapsulated' })
 | |
| 
 | |
|   fastify.inject('/not-found', (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|     t.equal(res.payload, 'this was not found')
 | |
|   })
 | |
| 
 | |
|   fastify.inject('/encapsulated/not-found', (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|     t.equal(res.payload, 'encapsulated was not found')
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('encapsulated custom 404 without - prefix hook and handler context', t => {
 | |
|   t.plan(13)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.decorate('foo', 42)
 | |
| 
 | |
|   fastify.register(function (instance, opts, done) {
 | |
|     instance.decorate('bar', 84)
 | |
| 
 | |
|     instance.addHook('onRequest', function (req, res, done) {
 | |
|       t.equal(this.foo, 42)
 | |
|       t.equal(this.bar, 84)
 | |
|       done()
 | |
|     })
 | |
|     instance.addHook('preHandler', function (request, reply, done) {
 | |
|       t.equal(this.foo, 42)
 | |
|       t.equal(this.bar, 84)
 | |
|       done()
 | |
|     })
 | |
|     instance.addHook('onSend', function (request, reply, payload, done) {
 | |
|       t.equal(this.foo, 42)
 | |
|       t.equal(this.bar, 84)
 | |
|       done()
 | |
|     })
 | |
|     instance.addHook('onResponse', function (request, reply, done) {
 | |
|       t.equal(this.foo, 42)
 | |
|       t.equal(this.bar, 84)
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     instance.setNotFoundHandler(function (request, reply) {
 | |
|       t.equal(this.foo, 42)
 | |
|       t.equal(this.bar, 84)
 | |
|       reply.code(404).send('custom not found')
 | |
|     })
 | |
| 
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   fastify.inject('/not-found', (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|     t.equal(res.payload, 'custom not found')
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('run hooks on default 404', t => {
 | |
|   t.plan(7)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.addHook('onRequest', function (req, res, done) {
 | |
|     t.pass('onRequest called')
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   fastify.addHook('preHandler', function (request, reply, done) {
 | |
|     t.pass('preHandler called')
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   fastify.addHook('onSend', function (request, reply, payload, done) {
 | |
|     t.pass('onSend called')
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   fastify.addHook('onResponse', function (request, reply, done) {
 | |
|     t.pass('onResponse called')
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.error(err)
 | |
| 
 | |
|     sget({
 | |
|       method: 'PUT',
 | |
|       url: 'http://localhost:' + fastify.server.address().port,
 | |
|       body: JSON.stringify({ hello: 'world' }),
 | |
|       headers: { 'Content-Type': 'application/json' }
 | |
|     }, (err, response, body) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 404)
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('run non-encapsulated plugin hooks on default 404', t => {
 | |
|   t.plan(6)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.register(fp(function (instance, options, done) {
 | |
|     instance.addHook('onRequest', function (req, res, done) {
 | |
|       t.pass('onRequest called')
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     instance.addHook('preHandler', function (request, reply, done) {
 | |
|       t.pass('preHandler called')
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     instance.addHook('onSend', function (request, reply, payload, done) {
 | |
|       t.pass('onSend called')
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     instance.addHook('onResponse', function (request, reply, done) {
 | |
|       t.pass('onResponse called')
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     done()
 | |
|   }))
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   fastify.inject({
 | |
|     method: 'POST',
 | |
|     url: '/',
 | |
|     payload: { hello: 'world' }
 | |
|   }, (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('run non-encapsulated plugin hooks on custom 404', t => {
 | |
|   t.plan(11)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   const plugin = fp((instance, opts, done) => {
 | |
|     instance.addHook('onRequest', function (req, res, done) {
 | |
|       t.pass('onRequest called')
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     instance.addHook('preHandler', function (request, reply, done) {
 | |
|       t.pass('preHandler called')
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     instance.addHook('onSend', function (request, reply, payload, done) {
 | |
|       t.pass('onSend called')
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     instance.addHook('onResponse', function (request, reply, done) {
 | |
|       t.pass('onResponse called')
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   fastify.register(plugin)
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   fastify.setNotFoundHandler(function (req, reply) {
 | |
|     reply.code(404).send('this was not found')
 | |
|   })
 | |
| 
 | |
|   fastify.register(plugin) // Registering plugin after handler also works
 | |
| 
 | |
|   fastify.inject({ url: '/not-found' }, (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|     t.equal(res.payload, 'this was not found')
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('run hook with encapsulated 404', t => {
 | |
|   t.plan(11)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.addHook('onRequest', function (req, res, done) {
 | |
|     t.pass('onRequest called')
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   fastify.addHook('preHandler', function (request, reply, done) {
 | |
|     t.pass('preHandler called')
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   fastify.addHook('onSend', function (request, reply, payload, done) {
 | |
|     t.pass('onSend called')
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   fastify.addHook('onResponse', function (request, reply, done) {
 | |
|     t.pass('onResponse called')
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   fastify.register(function (f, opts, done) {
 | |
|     f.setNotFoundHandler(function (req, reply) {
 | |
|       reply.code(404).send('this was not found 2')
 | |
|     })
 | |
| 
 | |
|     f.addHook('onRequest', function (req, res, done) {
 | |
|       t.pass('onRequest 2 called')
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     f.addHook('preHandler', function (request, reply, done) {
 | |
|       t.pass('preHandler 2 called')
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     f.addHook('onSend', function (request, reply, payload, done) {
 | |
|       t.pass('onSend 2 called')
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     f.addHook('onResponse', function (request, reply, done) {
 | |
|       t.pass('onResponse 2 called')
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     done()
 | |
|   }, { prefix: '/test' })
 | |
| 
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.error(err)
 | |
| 
 | |
|     sget({
 | |
|       method: 'PUT',
 | |
|       url: 'http://localhost:' + fastify.server.address().port + '/test',
 | |
|       body: JSON.stringify({ hello: 'world' }),
 | |
|       headers: { 'Content-Type': 'application/json' }
 | |
|     }, (err, response, body) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 404)
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('hooks check 404', t => {
 | |
|   t.plan(13)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   fastify.addHook('onSend', (req, reply, payload, done) => {
 | |
|     t.same(req.query, { foo: 'asd' })
 | |
|     t.ok('called', 'onSend')
 | |
|     done()
 | |
|   })
 | |
|   fastify.addHook('onRequest', (req, res, done) => {
 | |
|     t.ok('called', 'onRequest')
 | |
|     done()
 | |
|   })
 | |
|   fastify.addHook('onResponse', (request, reply, done) => {
 | |
|     t.ok('called', 'onResponse')
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.error(err)
 | |
| 
 | |
|     sget({
 | |
|       method: 'PUT',
 | |
|       url: 'http://localhost:' + fastify.server.address().port + '?foo=asd',
 | |
|       body: JSON.stringify({ hello: 'world' }),
 | |
|       headers: { 'Content-Type': 'application/json' }
 | |
|     }, (err, response, body) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 404)
 | |
|     })
 | |
| 
 | |
|     sget({
 | |
|       method: 'GET',
 | |
|       url: 'http://localhost:' + fastify.server.address().port + '/notSupported?foo=asd'
 | |
|     }, (err, response, body) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 404)
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('setNotFoundHandler should not suppress duplicated routes checking', t => {
 | |
|   t.plan(1)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   fastify.setNotFoundHandler(function (req, reply) {
 | |
|     reply.code(404).send('this was not found')
 | |
|   })
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.ok(err)
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('log debug for 404', t => {
 | |
|   t.plan(1)
 | |
| 
 | |
|   const Writable = require('stream').Writable
 | |
| 
 | |
|   const logStream = new Writable()
 | |
|   logStream.logs = []
 | |
|   logStream._write = function (chunk, encoding, callback) {
 | |
|     this.logs.push(chunk.toString())
 | |
|     callback()
 | |
|   }
 | |
| 
 | |
|   const fastify = Fastify({
 | |
|     logger: {
 | |
|       level: 'trace',
 | |
|       stream: logStream
 | |
|     }
 | |
|   })
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   t.test('log debug', t => {
 | |
|     t.plan(7)
 | |
|     fastify.inject({
 | |
|       method: 'GET',
 | |
|       url: '/not-found'
 | |
|     }, (err, response) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 404)
 | |
| 
 | |
|       const INFO_LEVEL = 30
 | |
|       t.equal(JSON.parse(logStream.logs[0]).msg, 'incoming request')
 | |
|       t.equal(JSON.parse(logStream.logs[1]).msg, 'Route GET:/not-found not found')
 | |
|       t.equal(JSON.parse(logStream.logs[1]).level, INFO_LEVEL)
 | |
|       t.equal(JSON.parse(logStream.logs[2]).msg, 'request completed')
 | |
|       t.equal(logStream.logs.length, 3)
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('Unknown method', t => {
 | |
|   t.plan(5)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.error(err)
 | |
| 
 | |
|     const handler = () => {}
 | |
|     // See https://github.com/fastify/light-my-request/pull/20
 | |
|     t.throws(() => fastify.inject({
 | |
|       method: 'UNKNWON_METHOD',
 | |
|       url: '/'
 | |
|     }, handler), Error)
 | |
| 
 | |
|     sget({
 | |
|       method: 'UNKNWON_METHOD',
 | |
|       url: 'http://localhost:' + fastify.server.address().port
 | |
|     }, (err, response, body) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 400)
 | |
|       t.strictSame(JSON.parse(body), {
 | |
|         error: 'Bad Request',
 | |
|         message: 'Client Error',
 | |
|         statusCode: 400
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('recognizes errors from the http-errors module', t => {
 | |
|   t.plan(5)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send(httpErrors.NotFound())
 | |
|   })
 | |
| 
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.error(err)
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'GET',
 | |
|       url: '/'
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       t.equal(res.statusCode, 404)
 | |
| 
 | |
|       sget('http://localhost:' + fastify.server.address().port, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         const obj = JSON.parse(body.toString())
 | |
|         t.strictSame(obj, {
 | |
|           error: 'Not Found',
 | |
|           message: 'Not Found',
 | |
|           statusCode: 404
 | |
|         })
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('the default 404 handler can be invoked inside a prefixed plugin', t => {
 | |
|   t.plan(3)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.register(function (instance, opts, done) {
 | |
|     instance.get('/path', function (request, reply) {
 | |
|       reply.send(httpErrors.NotFound())
 | |
|     })
 | |
| 
 | |
|     done()
 | |
|   }, { prefix: '/v1' })
 | |
| 
 | |
|   fastify.inject('/v1/path', (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|     t.strictSame(JSON.parse(res.payload), {
 | |
|       error: 'Not Found',
 | |
|       message: 'Not Found',
 | |
|       statusCode: 404
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('an inherited custom 404 handler can be invoked inside a prefixed plugin', t => {
 | |
|   t.plan(3)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.setNotFoundHandler(function (request, reply) {
 | |
|     reply.code(404).send('custom handler')
 | |
|   })
 | |
| 
 | |
|   fastify.register(function (instance, opts, done) {
 | |
|     instance.get('/path', function (request, reply) {
 | |
|       reply.send(httpErrors.NotFound())
 | |
|     })
 | |
| 
 | |
|     done()
 | |
|   }, { prefix: '/v1' })
 | |
| 
 | |
|   fastify.inject('/v1/path', (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|     t.same(JSON.parse(res.payload), {
 | |
|       error: 'Not Found',
 | |
|       message: 'Not Found',
 | |
|       statusCode: 404
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('encapsulated custom 404 handler without a prefix is the handler for the entire 404 level', t => {
 | |
|   t.plan(6)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.register(function (instance, opts, done) {
 | |
|     instance.setNotFoundHandler(function (request, reply) {
 | |
|       reply.code(404).send('custom handler')
 | |
|     })
 | |
| 
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   fastify.register(function (instance, opts, done) {
 | |
|     instance.register(function (instance2, opts, done) {
 | |
|       instance2.setNotFoundHandler(function (request, reply) {
 | |
|         reply.code(404).send('custom handler 2')
 | |
|       })
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     done()
 | |
|   }, { prefix: 'prefixed' })
 | |
| 
 | |
|   fastify.inject('/not-found', (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|     t.equal(res.payload, 'custom handler')
 | |
|   })
 | |
| 
 | |
|   fastify.inject('/prefixed/not-found', (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|     t.equal(res.payload, 'custom handler 2')
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('cannot set notFoundHandler after binding', t => {
 | |
|   t.plan(2)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.error(err)
 | |
| 
 | |
|     try {
 | |
|       fastify.setNotFoundHandler(() => { })
 | |
|       t.fail()
 | |
|     } catch (e) {
 | |
|       t.pass()
 | |
|     }
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('404 inside onSend', t => {
 | |
|   t.plan(3)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   let called = false
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   fastify.addHook('onSend', function (request, reply, payload, done) {
 | |
|     if (!called) {
 | |
|       called = true
 | |
|       done(new errors.NotFound())
 | |
|     } else {
 | |
|       done()
 | |
|     }
 | |
|   })
 | |
| 
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.error(err)
 | |
| 
 | |
|     sget({
 | |
|       method: 'GET',
 | |
|       url: 'http://localhost:' + fastify.server.address().port
 | |
|     }, (err, response, body) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 404)
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('Not found on supported method (should return a 404)', t => {
 | |
|   t.plan(5)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.error(err)
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'POST',
 | |
|       url: '/'
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       t.equal(res.statusCode, 404)
 | |
| 
 | |
|       sget({
 | |
|         method: 'POST',
 | |
|         url: 'http://localhost:' + fastify.server.address().port
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| // Return 404 instead of 405 see https://github.com/fastify/fastify/pull/862 for discussion
 | |
| test('Not found on unsupported method (should return a 404)', t => {
 | |
|   t.plan(5)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.all('/', function (req, reply) {
 | |
|     reply.send({ hello: 'world' })
 | |
|   })
 | |
| 
 | |
|   t.teardown(fastify.close.bind(fastify))
 | |
| 
 | |
|   fastify.listen(0, err => {
 | |
|     t.error(err)
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'PROPFIND',
 | |
|       url: '/'
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       t.equal(res.statusCode, 404)
 | |
| 
 | |
|       sget({
 | |
|         method: 'PROPFIND',
 | |
|         url: 'http://localhost:' + fastify.server.address().port
 | |
|       }, (err, response, body) => {
 | |
|         t.error(err)
 | |
|         t.equal(response.statusCode, 404)
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| // https://github.com/fastify/fastify/issues/868
 | |
| test('onSend hooks run when an encapsulated route invokes the notFound handler', t => {
 | |
|   t.plan(3)
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.register((instance, options, done) => {
 | |
|     instance.addHook('onSend', (request, reply, payload, done) => {
 | |
|       t.pass('onSend hook called')
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     instance.get('/', (request, reply) => {
 | |
|       reply.send(new errors.NotFound())
 | |
|     })
 | |
| 
 | |
|     done()
 | |
|   })
 | |
| 
 | |
|   fastify.inject('/', (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|   })
 | |
| })
 | |
| 
 | |
| // https://github.com/fastify/fastify/issues/713
 | |
| test('preHandler option for setNotFoundHandler', t => {
 | |
|   t.plan(10)
 | |
| 
 | |
|   t.test('preHandler option', t => {
 | |
|     t.plan(2)
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.setNotFoundHandler({
 | |
|       preHandler: (req, reply, done) => {
 | |
|         req.body.preHandler = true
 | |
|         done()
 | |
|       }
 | |
|     }, function (req, reply) {
 | |
|       reply.code(404).send(req.body)
 | |
|     })
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'POST',
 | |
|       url: '/not-found',
 | |
|       payload: { hello: 'world' }
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       const payload = JSON.parse(res.payload)
 | |
|       t.same(payload, { preHandler: true, hello: 'world' })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   // https://github.com/fastify/fastify/issues/2229
 | |
|   t.test('preHandler hook in setNotFoundHandler should be called when callNotFound', { timeout: 40000 }, t => {
 | |
|     t.plan(2)
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.setNotFoundHandler({
 | |
|       preHandler: (req, reply, done) => {
 | |
|         req.body.preHandler = true
 | |
|         done()
 | |
|       }
 | |
|     }, function (req, reply) {
 | |
|       reply.code(404).send(req.body)
 | |
|     })
 | |
| 
 | |
|     fastify.post('/', function (req, reply) {
 | |
|       reply.callNotFound()
 | |
|     })
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'POST',
 | |
|       url: '/',
 | |
|       payload: { hello: 'world' }
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       const payload = JSON.parse(res.payload)
 | |
|       t.same(payload, { preHandler: true, hello: 'world' })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('preHandler hook in setNotFoundHandler should accept an array of functions and be called when callNotFound', t => {
 | |
|     t.plan(2)
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.setNotFoundHandler({
 | |
|       preHandler: [
 | |
|         (req, reply, done) => {
 | |
|           req.body.preHandler1 = true
 | |
|           done()
 | |
|         },
 | |
|         (req, reply, done) => {
 | |
|           req.body.preHandler2 = true
 | |
|           done()
 | |
|         }
 | |
|       ]
 | |
|     }, function (req, reply) {
 | |
|       reply.code(404).send(req.body)
 | |
|     })
 | |
| 
 | |
|     fastify.post('/', function (req, reply) {
 | |
|       reply.callNotFound()
 | |
|     })
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'POST',
 | |
|       url: '/',
 | |
|       payload: { hello: 'world' }
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       const payload = JSON.parse(res.payload)
 | |
|       t.same(payload, { preHandler1: true, preHandler2: true, hello: 'world' })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('preHandler option should be called after preHandler hook', t => {
 | |
|     t.plan(2)
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.addHook('preHandler', (req, reply, done) => {
 | |
|       req.body.check = 'a'
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     fastify.setNotFoundHandler({
 | |
|       preHandler: (req, reply, done) => {
 | |
|         req.body.check += 'b'
 | |
|         done()
 | |
|       }
 | |
|     }, (req, reply) => {
 | |
|       reply.send(req.body)
 | |
|     })
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'POST',
 | |
|       url: '/',
 | |
|       payload: { hello: 'world' }
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       const payload = JSON.parse(res.payload)
 | |
|       t.same(payload, { check: 'ab', hello: 'world' })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('preHandler option should be unique per prefix', t => {
 | |
|     t.plan(4)
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.setNotFoundHandler({
 | |
|       preHandler: (req, reply, done) => {
 | |
|         req.body.hello = 'earth'
 | |
|         done()
 | |
|       }
 | |
|     }, (req, reply) => {
 | |
|       reply.send(req.body)
 | |
|     })
 | |
| 
 | |
|     fastify.register(function (i, o, n) {
 | |
|       i.setNotFoundHandler((req, reply) => {
 | |
|         reply.send(req.body)
 | |
|       })
 | |
| 
 | |
|       n()
 | |
|     }, { prefix: '/no' })
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'POST',
 | |
|       url: '/not-found',
 | |
|       payload: { hello: 'world' }
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       const payload = JSON.parse(res.payload)
 | |
|       t.same(payload, { hello: 'earth' })
 | |
|     })
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'POST',
 | |
|       url: '/no/not-found',
 | |
|       payload: { hello: 'world' }
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       const payload = JSON.parse(res.payload)
 | |
|       t.same(payload, { hello: 'world' })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('preHandler option should handle errors', t => {
 | |
|     t.plan(3)
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.setNotFoundHandler({
 | |
|       preHandler: (req, reply, done) => {
 | |
|         done(new Error('kaboom'))
 | |
|       }
 | |
|     }, (req, reply) => {
 | |
|       reply.send(req.body)
 | |
|     })
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'POST',
 | |
|       url: '/not-found',
 | |
|       payload: { hello: 'world' }
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       const payload = JSON.parse(res.payload)
 | |
|       t.equal(res.statusCode, 500)
 | |
|       t.same(payload, {
 | |
|         message: 'kaboom',
 | |
|         error: 'Internal Server Error',
 | |
|         statusCode: 500
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('preHandler option should handle errors with custom status code', t => {
 | |
|     t.plan(3)
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.setNotFoundHandler({
 | |
|       preHandler: (req, reply, done) => {
 | |
|         reply.code(401)
 | |
|         done(new Error('go away'))
 | |
|       }
 | |
|     }, (req, reply) => {
 | |
|       reply.send(req.body)
 | |
|     })
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'POST',
 | |
|       url: '/not-found',
 | |
|       payload: { hello: 'world' }
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       const payload = JSON.parse(res.payload)
 | |
|       t.equal(res.statusCode, 401)
 | |
|       t.same(payload, {
 | |
|         message: 'go away',
 | |
|         error: 'Unauthorized',
 | |
|         statusCode: 401
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('preHandler option could accept an array of functions', t => {
 | |
|     t.plan(2)
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.setNotFoundHandler({
 | |
|       preHandler: [
 | |
|         (req, reply, done) => {
 | |
|           req.body.preHandler = 'a'
 | |
|           done()
 | |
|         },
 | |
|         (req, reply, done) => {
 | |
|           req.body.preHandler += 'b'
 | |
|           done()
 | |
|         }
 | |
|       ]
 | |
|     }, (req, reply) => {
 | |
|       reply.send(req.body)
 | |
|     })
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'POST',
 | |
|       url: '/not-found',
 | |
|       payload: { hello: 'world' }
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       const payload = JSON.parse(res.payload)
 | |
|       t.same(payload, { preHandler: 'ab', hello: 'world' })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('preHandler option does not interfere with preHandler', t => {
 | |
|     t.plan(4)
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.addHook('preHandler', (req, reply, done) => {
 | |
|       req.body.check = 'a'
 | |
|       done()
 | |
|     })
 | |
| 
 | |
|     fastify.setNotFoundHandler({
 | |
|       preHandler: (req, reply, done) => {
 | |
|         req.body.check += 'b'
 | |
|         done()
 | |
|       }
 | |
|     }, (req, reply) => {
 | |
|       reply.send(req.body)
 | |
|     })
 | |
| 
 | |
|     fastify.register(function (i, o, n) {
 | |
|       i.setNotFoundHandler((req, reply) => {
 | |
|         reply.send(req.body)
 | |
|       })
 | |
| 
 | |
|       n()
 | |
|     }, { prefix: '/no' })
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'post',
 | |
|       url: '/not-found',
 | |
|       payload: { hello: 'world' }
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       const payload = JSON.parse(res.payload)
 | |
|       t.same(payload, { check: 'ab', hello: 'world' })
 | |
|     })
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'post',
 | |
|       url: '/no/not-found',
 | |
|       payload: { hello: 'world' }
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       const payload = JSON.parse(res.payload)
 | |
|       t.same(payload, { check: 'a', hello: 'world' })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('preHandler option should keep the context', t => {
 | |
|     t.plan(3)
 | |
|     const fastify = Fastify()
 | |
| 
 | |
|     fastify.decorate('foo', 42)
 | |
| 
 | |
|     fastify.setNotFoundHandler({
 | |
|       preHandler: function (req, reply, done) {
 | |
|         t.equal(this.foo, 42)
 | |
|         this.foo += 1
 | |
|         req.body.foo = this.foo
 | |
|         done()
 | |
|       }
 | |
|     }, (req, reply) => {
 | |
|       reply.send(req.body)
 | |
|     })
 | |
| 
 | |
|     fastify.inject({
 | |
|       method: 'POST',
 | |
|       url: '/not-found',
 | |
|       payload: { hello: 'world' }
 | |
|     }, (err, res) => {
 | |
|       t.error(err)
 | |
|       const payload = JSON.parse(res.payload)
 | |
|       t.same(payload, { foo: 43, hello: 'world' })
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('reply.notFound invoked the notFound handler', t => {
 | |
|   t.plan(3)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.setNotFoundHandler((req, reply) => {
 | |
|     reply.code(404).send(new Error('kaboom'))
 | |
|   })
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.callNotFound()
 | |
|   })
 | |
| 
 | |
|   fastify.inject({
 | |
|     url: '/',
 | |
|     method: 'GET'
 | |
|   }, (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|     t.same(JSON.parse(res.payload), {
 | |
|       error: 'Not Found',
 | |
|       message: 'kaboom',
 | |
|       statusCode: 404
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('The custom error handler should be invoked after the custom not found handler', t => {
 | |
|   t.plan(6)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
|   const order = [1, 2]
 | |
| 
 | |
|   fastify.setErrorHandler((err, req, reply) => {
 | |
|     t.equal(order.shift(), 2)
 | |
|     t.type(err, Error)
 | |
|     reply.send(err)
 | |
|   })
 | |
| 
 | |
|   fastify.setNotFoundHandler((req, reply) => {
 | |
|     t.equal(order.shift(), 1)
 | |
|     reply.code(404).send(new Error('kaboom'))
 | |
|   })
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.callNotFound()
 | |
|   })
 | |
| 
 | |
|   fastify.inject({
 | |
|     url: '/',
 | |
|     method: 'GET'
 | |
|   }, (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|     t.same(JSON.parse(res.payload), {
 | |
|       error: 'Not Found',
 | |
|       message: 'kaboom',
 | |
|       statusCode: 404
 | |
|     })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('If the custom not found handler does not use an Error, the custom error handler should not be called', t => {
 | |
|   t.plan(3)
 | |
| 
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.setErrorHandler((_err, req, reply) => {
 | |
|     t.fail('Should not be called')
 | |
|   })
 | |
| 
 | |
|   fastify.setNotFoundHandler((req, reply) => {
 | |
|     reply.code(404).send('kaboom')
 | |
|   })
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.callNotFound()
 | |
|   })
 | |
| 
 | |
|   fastify.inject({
 | |
|     url: '/',
 | |
|     method: 'GET'
 | |
|   }, (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|     t.equal(res.payload, 'kaboom')
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('preValidation option', t => {
 | |
|   t.plan(3)
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.decorate('foo', true)
 | |
| 
 | |
|   fastify.setNotFoundHandler({
 | |
|     preValidation: function (req, reply, done) {
 | |
|       t.ok(this.foo)
 | |
|       done()
 | |
|     }
 | |
|   }, function (req, reply) {
 | |
|     reply.code(404).send(req.body)
 | |
|   })
 | |
| 
 | |
|   fastify.inject({
 | |
|     method: 'POST',
 | |
|     url: '/not-found',
 | |
|     payload: { hello: 'world' }
 | |
|   }, (err, res) => {
 | |
|     t.error(err)
 | |
|     const payload = JSON.parse(res.payload)
 | |
|     t.same(payload, { hello: 'world' })
 | |
|   })
 | |
| })
 | |
| 
 | |
| t.test('preValidation option could accept an array of functions', t => {
 | |
|   t.plan(4)
 | |
|   const fastify = Fastify()
 | |
| 
 | |
|   fastify.setNotFoundHandler({
 | |
|     preValidation: [
 | |
|       (req, reply, done) => {
 | |
|         t.ok('called')
 | |
|         done()
 | |
|       },
 | |
|       (req, reply, done) => {
 | |
|         t.ok('called')
 | |
|         done()
 | |
|       }
 | |
|     ]
 | |
|   }, (req, reply) => {
 | |
|     reply.send(req.body)
 | |
|   })
 | |
| 
 | |
|   fastify.inject({
 | |
|     method: 'POST',
 | |
|     url: '/not-found',
 | |
|     payload: { hello: 'world' }
 | |
|   }, (err, res) => {
 | |
|     t.error(err)
 | |
|     const payload = JSON.parse(res.payload)
 | |
|     t.same(payload, { hello: 'world' })
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('Should fail to invoke callNotFound inside a 404 handler', t => {
 | |
|   t.plan(5)
 | |
| 
 | |
|   let fastify = null
 | |
|   const logStream = split(JSON.parse)
 | |
|   try {
 | |
|     fastify = Fastify({
 | |
|       logger: {
 | |
|         stream: logStream,
 | |
|         level: 'warn'
 | |
|       }
 | |
|     })
 | |
|   } catch (e) {
 | |
|     t.fail()
 | |
|   }
 | |
| 
 | |
|   fastify.setNotFoundHandler((req, reply) => {
 | |
|     reply.callNotFound()
 | |
|   })
 | |
| 
 | |
|   fastify.get('/', function (req, reply) {
 | |
|     reply.callNotFound()
 | |
|   })
 | |
| 
 | |
|   logStream.once('data', line => {
 | |
|     t.equal(line.msg, 'Trying to send a NotFound error inside a 404 handler. Sending basic 404 response.')
 | |
|     t.equal(line.level, 40)
 | |
|   })
 | |
| 
 | |
|   fastify.inject({
 | |
|     url: '/',
 | |
|     method: 'GET'
 | |
|   }, (err, res) => {
 | |
|     t.error(err)
 | |
|     t.equal(res.statusCode, 404)
 | |
|     t.equal(res.payload, '404 Not Found')
 | |
|   })
 | |
| })
 | |
| 
 | |
| test('400 in case of bad url (pre find-my-way v2.2.0 was a 404)', t => {
 | |
|   t.test('Dynamic route', t => {
 | |
|     t.plan(3)
 | |
|     const fastify = Fastify()
 | |
|     fastify.get('/hello/:id', () => t.fail('we should not be here'))
 | |
|     fastify.inject({
 | |
|       url: '/hello/%world',
 | |
|       method: 'GET'
 | |
|     }, (err, response) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 400)
 | |
|       t.same(JSON.parse(response.payload), {
 | |
|         error: 'Bad Request',
 | |
|         message: "'%world' is not a valid url component",
 | |
|         statusCode: 400
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('Wildcard', t => {
 | |
|     t.plan(3)
 | |
|     const fastify = Fastify()
 | |
|     fastify.get('*', () => t.fail('we should not be here'))
 | |
|     fastify.inject({
 | |
|       url: '/hello/%world',
 | |
|       method: 'GET'
 | |
|     }, (err, response) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 400)
 | |
|       t.same(JSON.parse(response.payload), {
 | |
|         error: 'Bad Request',
 | |
|         message: "'/hello/%world' is not a valid url component",
 | |
|         statusCode: 400
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('No route registered', t => {
 | |
|     t.plan(3)
 | |
|     const fastify = Fastify()
 | |
|     fastify.inject({
 | |
|       url: '/%c0',
 | |
|       method: 'GET'
 | |
|     }, (err, response) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 404)
 | |
|       t.same(JSON.parse(response.payload), {
 | |
|         error: 'Not Found',
 | |
|         message: 'Route GET:/%c0 not found',
 | |
|         statusCode: 404
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('Only / is registered', t => {
 | |
|     t.plan(3)
 | |
|     const fastify = Fastify({ logger: true })
 | |
|     fastify.get('/', () => t.fail('we should not be here'))
 | |
|     fastify.inject({
 | |
|       url: '/%c0',
 | |
|       method: 'GET'
 | |
|     }, (err, response) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 404)
 | |
|       t.same(JSON.parse(response.payload), {
 | |
|         error: 'Not Found',
 | |
|         message: 'Route GET:/%c0 not found',
 | |
|         statusCode: 404
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.test('customized 404', t => {
 | |
|     t.plan(3)
 | |
|     const fastify = Fastify({ logger: true })
 | |
|     fastify.get('/', () => t.fail('we should not be here'))
 | |
|     fastify.setNotFoundHandler(function (req, reply) {
 | |
|       reply.code(404).send('this was not found')
 | |
|     })
 | |
|     fastify.inject({
 | |
|       url: '/%c0',
 | |
|       method: 'GET'
 | |
|     }, (err, response) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 404)
 | |
|       t.same(response.payload, 'this was not found')
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.end()
 | |
| })
 | |
| 
 | |
| test('setNotFoundHandler should be chaining fastify instance', t => {
 | |
|   t.test('Register route after setNotFoundHandler', t => {
 | |
|     t.plan(6)
 | |
|     const fastify = Fastify()
 | |
|     fastify.setNotFoundHandler(function (_req, reply) {
 | |
|       reply.code(404).send('this was not found')
 | |
|     }).get('/valid-route', function (_req, reply) {
 | |
|       reply.send('valid route')
 | |
|     })
 | |
| 
 | |
|     fastify.inject({
 | |
|       url: '/invalid-route',
 | |
|       method: 'GET'
 | |
|     }, (err, response) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 404)
 | |
|       t.equal(response.payload, 'this was not found')
 | |
|     })
 | |
| 
 | |
|     fastify.inject({
 | |
|       url: '/valid-route',
 | |
|       method: 'GET'
 | |
|     }, (err, response) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 200)
 | |
|       t.equal(response.payload, 'valid route')
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.end()
 | |
| })
 | |
| 
 | |
| test('Send 404 when frameworkError calls reply.callNotFound', t => {
 | |
|   t.test('Dynamic route', t => {
 | |
|     t.plan(4)
 | |
|     const fastify = Fastify({
 | |
|       logger: true,
 | |
|       frameworkErrors: (error, req, reply) => {
 | |
|         t.equal(error.message, "'%world' is not a valid url component")
 | |
|         return reply.callNotFound()
 | |
|       }
 | |
|     })
 | |
|     fastify.get('/hello/:id', () => t.fail('we should not be here'))
 | |
|     fastify.inject({
 | |
|       url: '/hello/%world',
 | |
|       method: 'GET'
 | |
|     }, (err, response) => {
 | |
|       t.error(err)
 | |
|       t.equal(response.statusCode, 404)
 | |
|       t.equal(response.payload, '404 Not Found')
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   t.end()
 | |
| })
 |