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.
		
		
		
		
		
			
		
			
				
					
					
						
							1283 lines
						
					
					
						
							28 KiB
						
					
					
				
			
		
		
	
	
							1283 lines
						
					
					
						
							28 KiB
						
					
					
				'use strict'
 | 
						|
 | 
						|
const stream = require('stream')
 | 
						|
const split = require('split2')
 | 
						|
const t = require('tap')
 | 
						|
const test = t.test
 | 
						|
const sget = require('simple-get').concat
 | 
						|
const joi = require('@hapi/joi')
 | 
						|
const Fastify = require('..')
 | 
						|
const proxyquire = require('proxyquire')
 | 
						|
const { FST_ERR_INVALID_URL } = require('../lib/errors')
 | 
						|
 | 
						|
test('route', t => {
 | 
						|
  t.plan(9)
 | 
						|
  const test = t.test
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  test('route - get', t => {
 | 
						|
    t.plan(1)
 | 
						|
    try {
 | 
						|
      fastify.route({
 | 
						|
        method: 'GET',
 | 
						|
        url: '/',
 | 
						|
        schema: {
 | 
						|
          response: {
 | 
						|
            '2xx': {
 | 
						|
              type: 'object',
 | 
						|
              properties: {
 | 
						|
                hello: {
 | 
						|
                  type: 'string'
 | 
						|
                }
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        },
 | 
						|
        handler: function (req, reply) {
 | 
						|
          reply.send({ hello: 'world' })
 | 
						|
        }
 | 
						|
      })
 | 
						|
      t.pass()
 | 
						|
    } catch (e) {
 | 
						|
      t.fail()
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  test('missing schema - route', t => {
 | 
						|
    t.plan(1)
 | 
						|
    try {
 | 
						|
      fastify.route({
 | 
						|
        method: 'GET',
 | 
						|
        url: '/missing',
 | 
						|
        handler: function (req, reply) {
 | 
						|
          reply.send({ hello: 'world' })
 | 
						|
        }
 | 
						|
      })
 | 
						|
      t.pass()
 | 
						|
    } catch (e) {
 | 
						|
      t.fail()
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  test('invalid handler attribute - route', t => {
 | 
						|
    t.plan(1)
 | 
						|
    try {
 | 
						|
      fastify.get('/', { handler: 'not a function' }, () => {})
 | 
						|
      t.fail()
 | 
						|
    } catch (e) {
 | 
						|
      t.pass()
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  test('Multiple methods', t => {
 | 
						|
    t.plan(1)
 | 
						|
    try {
 | 
						|
      fastify.route({
 | 
						|
        method: ['GET', 'DELETE'],
 | 
						|
        url: '/multiple',
 | 
						|
        handler: function (req, reply) {
 | 
						|
          reply.send({ hello: 'world' })
 | 
						|
        }
 | 
						|
      })
 | 
						|
      t.pass()
 | 
						|
    } catch (e) {
 | 
						|
      t.fail()
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  test('Add multiple methods', t => {
 | 
						|
    t.plan(1)
 | 
						|
    try {
 | 
						|
      fastify.get('/add-multiple', function (req, reply) {
 | 
						|
        reply.send({ hello: 'Bob!' })
 | 
						|
      })
 | 
						|
      fastify.route({
 | 
						|
        method: ['PUT', 'DELETE'],
 | 
						|
        url: '/add-multiple',
 | 
						|
        handler: function (req, reply) {
 | 
						|
          reply.send({ hello: 'world' })
 | 
						|
        }
 | 
						|
      })
 | 
						|
      t.pass()
 | 
						|
    } catch (e) {
 | 
						|
      t.fail()
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.listen(0, function (err) {
 | 
						|
    if (err) t.error(err)
 | 
						|
    fastify.server.unref()
 | 
						|
 | 
						|
    test('cannot add another route after binding', t => {
 | 
						|
      t.plan(1)
 | 
						|
      try {
 | 
						|
        fastify.route({
 | 
						|
          method: 'GET',
 | 
						|
          url: '/another-get-route',
 | 
						|
          handler: function (req, reply) {
 | 
						|
            reply.send({ hello: 'world' })
 | 
						|
          }
 | 
						|
        })
 | 
						|
        t.fail()
 | 
						|
      } catch (e) {
 | 
						|
        t.pass()
 | 
						|
      }
 | 
						|
    })
 | 
						|
 | 
						|
    test('route - get', t => {
 | 
						|
      t.plan(3)
 | 
						|
      sget({
 | 
						|
        method: 'GET',
 | 
						|
        url: 'http://localhost:' + fastify.server.address().port
 | 
						|
      }, (err, response, body) => {
 | 
						|
        t.error(err)
 | 
						|
        t.equal(response.statusCode, 200)
 | 
						|
        t.same(JSON.parse(body), { hello: 'world' })
 | 
						|
      })
 | 
						|
    })
 | 
						|
 | 
						|
    test('route - missing schema', t => {
 | 
						|
      t.plan(3)
 | 
						|
      sget({
 | 
						|
        method: 'GET',
 | 
						|
        url: 'http://localhost:' + fastify.server.address().port + '/missing'
 | 
						|
      }, (err, response, body) => {
 | 
						|
        t.error(err)
 | 
						|
        t.equal(response.statusCode, 200)
 | 
						|
        t.same(JSON.parse(body), { hello: 'world' })
 | 
						|
      })
 | 
						|
    })
 | 
						|
 | 
						|
    test('route - multiple methods', t => {
 | 
						|
      t.plan(6)
 | 
						|
      sget({
 | 
						|
        method: 'GET',
 | 
						|
        url: 'http://localhost:' + fastify.server.address().port + '/multiple'
 | 
						|
      }, (err, response, body) => {
 | 
						|
        t.error(err)
 | 
						|
        t.equal(response.statusCode, 200)
 | 
						|
        t.same(JSON.parse(body), { hello: 'world' })
 | 
						|
      })
 | 
						|
 | 
						|
      sget({
 | 
						|
        method: 'DELETE',
 | 
						|
        url: 'http://localhost:' + fastify.server.address().port + '/multiple'
 | 
						|
      }, (err, response, body) => {
 | 
						|
        t.error(err)
 | 
						|
        t.equal(response.statusCode, 200)
 | 
						|
        t.same(JSON.parse(body), { hello: 'world' })
 | 
						|
      })
 | 
						|
    })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('invalid schema - route', t => {
 | 
						|
  t.plan(3)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
  fastify.route({
 | 
						|
    handler: () => {},
 | 
						|
    method: 'GET',
 | 
						|
    url: '/invalid',
 | 
						|
    schema: {
 | 
						|
      querystring: {
 | 
						|
        id: 'string'
 | 
						|
      }
 | 
						|
    }
 | 
						|
  })
 | 
						|
  fastify.after(err => {
 | 
						|
    t.notOk(err, 'the error is throw on preReady')
 | 
						|
  })
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.equal(err.code, 'FST_ERR_SCH_VALIDATION_BUILD')
 | 
						|
    t.match(err.message, /Failed building the validation schema for GET: \/invalid/)
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('same route definition object on multiple prefixes', async t => {
 | 
						|
  t.plan(2)
 | 
						|
 | 
						|
  const routeObject = {
 | 
						|
    handler: () => {},
 | 
						|
    method: 'GET',
 | 
						|
    url: '/simple'
 | 
						|
  }
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(async function (f) {
 | 
						|
    f.addHook('onRoute', (routeOptions) => {
 | 
						|
      t.equal(routeOptions.url, '/v1/simple')
 | 
						|
    })
 | 
						|
    f.route(routeObject)
 | 
						|
  }, { prefix: '/v1' })
 | 
						|
  fastify.register(async function (f) {
 | 
						|
    f.addHook('onRoute', (routeOptions) => {
 | 
						|
      t.equal(routeOptions.url, '/v2/simple')
 | 
						|
    })
 | 
						|
    f.route(routeObject)
 | 
						|
  }, { prefix: '/v2' })
 | 
						|
 | 
						|
  await fastify.ready()
 | 
						|
})
 | 
						|
 | 
						|
test('path can be specified in place of uri', t => {
 | 
						|
  t.plan(3)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/path',
 | 
						|
    handler: function (req, reply) {
 | 
						|
      reply.send({ hello: 'world' })
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  const reqOpts = {
 | 
						|
    method: 'GET',
 | 
						|
    url: '/path'
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.inject(reqOpts, (err, res) => {
 | 
						|
    t.error(err)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.same(JSON.parse(res.payload), { hello: 'world' })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('invalid bodyLimit option - route', t => {
 | 
						|
  t.plan(2)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  try {
 | 
						|
    fastify.route({
 | 
						|
      bodyLimit: false,
 | 
						|
      method: 'PUT',
 | 
						|
      handler: () => null
 | 
						|
    })
 | 
						|
    t.fail('bodyLimit must be an integer')
 | 
						|
  } catch (err) {
 | 
						|
    t.equal(err.message, "'bodyLimit' option must be an integer > 0. Got 'false'")
 | 
						|
  }
 | 
						|
 | 
						|
  try {
 | 
						|
    fastify.post('/url', { bodyLimit: 10000.1 }, () => null)
 | 
						|
    t.fail('bodyLimit must be an integer')
 | 
						|
  } catch (err) {
 | 
						|
    t.equal(err.message, "'bodyLimit' option must be an integer > 0. Got '10000.1'")
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
test('handler function in options of shorthand route should works correctly', t => {
 | 
						|
  t.plan(3)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
  fastify.get('/foo', {
 | 
						|
    handler: (req, reply) => {
 | 
						|
      reply.send({ hello: 'world' })
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'GET',
 | 
						|
    url: '/foo'
 | 
						|
  }, (err, res) => {
 | 
						|
    t.error(err)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.same(JSON.parse(res.payload), { hello: 'world' })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('does not mutate joi schemas', t => {
 | 
						|
  t.plan(4)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
  function validatorCompiler ({ schema, method, url, httpPart }) {
 | 
						|
    // Needed to extract the params part,
 | 
						|
    // without the JSON-schema encapsulation
 | 
						|
    // that is automatically added by the short
 | 
						|
    // form of params.
 | 
						|
    schema = joi.object(schema.properties)
 | 
						|
 | 
						|
    return validateHttpData
 | 
						|
 | 
						|
    function validateHttpData (data) {
 | 
						|
      return schema.validate(data)
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.setValidatorCompiler(validatorCompiler)
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    path: '/foo/:an_id',
 | 
						|
    method: 'GET',
 | 
						|
    schema: {
 | 
						|
      params: { an_id: joi.number() }
 | 
						|
    },
 | 
						|
    handler (req, res) {
 | 
						|
      t.same(req.params, { an_id: 42 })
 | 
						|
      res.send({ hello: 'world' })
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'GET',
 | 
						|
    url: '/foo/42'
 | 
						|
  }, (err, result) => {
 | 
						|
    t.error(err)
 | 
						|
    t.equal(result.statusCode, 200)
 | 
						|
    t.same(JSON.parse(result.payload), { hello: 'world' })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('multiple routes with one schema', t => {
 | 
						|
  t.plan(2)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  const schema = {
 | 
						|
    query: {
 | 
						|
      id: { type: 'number' }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    schema,
 | 
						|
    method: 'GET',
 | 
						|
    path: '/first/:id',
 | 
						|
    handler (req, res) {
 | 
						|
      res.send({ hello: 'world' })
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    schema,
 | 
						|
    method: 'GET',
 | 
						|
    path: '/second/:id',
 | 
						|
    handler (req, res) {
 | 
						|
      res.send({ hello: 'world' })
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.ready(error => {
 | 
						|
    t.error(error)
 | 
						|
    t.same(schema, schema)
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('route error handler overrides default error handler', t => {
 | 
						|
  t.plan(4)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  const customRouteErrorHandler = (error, request, reply) => {
 | 
						|
    t.equal(error.message, 'Wrong Pot Error')
 | 
						|
 | 
						|
    reply.code(418).send({
 | 
						|
      message: 'Make a brew',
 | 
						|
      statusCode: 418,
 | 
						|
      error: 'Wrong Pot Error'
 | 
						|
    })
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/coffee',
 | 
						|
    handler: (req, res) => {
 | 
						|
      res.send(new Error('Wrong Pot Error'))
 | 
						|
    },
 | 
						|
    errorHandler: customRouteErrorHandler
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'GET',
 | 
						|
    url: '/coffee'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 418)
 | 
						|
    t.same(JSON.parse(res.payload), {
 | 
						|
      message: 'Make a brew',
 | 
						|
      statusCode: 418,
 | 
						|
      error: 'Wrong Pot Error'
 | 
						|
    })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('route error handler does not affect other routes', t => {
 | 
						|
  t.plan(3)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  const customRouteErrorHandler = (error, request, reply) => {
 | 
						|
    t.equal(error.message, 'Wrong Pot Error')
 | 
						|
 | 
						|
    reply.code(418).send({
 | 
						|
      message: 'Make a brew',
 | 
						|
      statusCode: 418,
 | 
						|
      error: 'Wrong Pot Error'
 | 
						|
    })
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/coffee',
 | 
						|
    handler: (req, res) => {
 | 
						|
      res.send(new Error('Wrong Pot Error'))
 | 
						|
    },
 | 
						|
    errorHandler: customRouteErrorHandler
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/tea',
 | 
						|
    handler: (req, res) => {
 | 
						|
      res.send(new Error('No tea today'))
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'GET',
 | 
						|
    url: '/tea'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 500)
 | 
						|
    t.same(JSON.parse(res.payload), {
 | 
						|
      message: 'No tea today',
 | 
						|
      statusCode: 500,
 | 
						|
      error: 'Internal Server Error'
 | 
						|
    })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('async error handler for a route', t => {
 | 
						|
  t.plan(4)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  const customRouteErrorHandler = async (error, request, reply) => {
 | 
						|
    t.equal(error.message, 'Delayed Pot Error')
 | 
						|
    reply.code(418)
 | 
						|
    return {
 | 
						|
      message: 'Make a brew sometime later',
 | 
						|
      statusCode: 418,
 | 
						|
      error: 'Delayed Pot Error'
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/late-coffee',
 | 
						|
    handler: (req, res) => {
 | 
						|
      res.send(new Error('Delayed Pot Error'))
 | 
						|
    },
 | 
						|
    errorHandler: customRouteErrorHandler
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'GET',
 | 
						|
    url: '/late-coffee'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 418)
 | 
						|
    t.same(JSON.parse(res.payload), {
 | 
						|
      message: 'Make a brew sometime later',
 | 
						|
      statusCode: 418,
 | 
						|
      error: 'Delayed Pot Error'
 | 
						|
    })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('route error handler overrides global custom error handler', t => {
 | 
						|
  t.plan(4)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  const customGlobalErrorHandler = (error, request, reply) => {
 | 
						|
    t.error(error)
 | 
						|
    reply.code(429).send({ message: 'Too much coffee' })
 | 
						|
  }
 | 
						|
 | 
						|
  const customRouteErrorHandler = (error, request, reply) => {
 | 
						|
    t.equal(error.message, 'Wrong Pot Error')
 | 
						|
    reply.code(418).send({
 | 
						|
      message: 'Make a brew',
 | 
						|
      statusCode: 418,
 | 
						|
      error: 'Wrong Pot Error'
 | 
						|
    })
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.setErrorHandler(customGlobalErrorHandler)
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/more-coffee',
 | 
						|
    handler: (req, res) => {
 | 
						|
      res.send(new Error('Wrong Pot Error'))
 | 
						|
    },
 | 
						|
    errorHandler: customRouteErrorHandler
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'GET',
 | 
						|
    url: '/more-coffee'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 418)
 | 
						|
    t.same(JSON.parse(res.payload), {
 | 
						|
      message: 'Make a brew',
 | 
						|
      statusCode: 418,
 | 
						|
      error: 'Wrong Pot Error'
 | 
						|
    })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('throws when route with empty url', async t => {
 | 
						|
  t.plan(1)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
  try {
 | 
						|
    await fastify.route({
 | 
						|
      method: 'GET',
 | 
						|
      url: '',
 | 
						|
      handler: (req, res) => {
 | 
						|
        res.send('hi!')
 | 
						|
      }
 | 
						|
    }).ready()
 | 
						|
  } catch (err) {
 | 
						|
    t.equal(err.message, 'The first character of a path should be `/` or `*`')
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
test('throws when route with empty url in shorthand declaration', async t => {
 | 
						|
  t.plan(1)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
  try {
 | 
						|
    await fastify.get(
 | 
						|
      '',
 | 
						|
      async function handler () { return {} }
 | 
						|
    ).ready()
 | 
						|
  } catch (err) {
 | 
						|
    t.equal(err.message, 'The path could not be empty')
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
test('throws when route-level error handler is not a function', t => {
 | 
						|
  t.plan(1)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  try {
 | 
						|
    fastify.route({
 | 
						|
      method: 'GET',
 | 
						|
      url: '/tea',
 | 
						|
      handler: (req, res) => {
 | 
						|
        res.send('hi!')
 | 
						|
      },
 | 
						|
      errorHandler: 'teapot'
 | 
						|
    })
 | 
						|
  } catch (err) {
 | 
						|
    t.equal(err.message, 'Error Handler for GET:/tea route, if defined, must be a function')
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
test('Creates a HEAD route for each GET one', t => {
 | 
						|
  t.plan(8)
 | 
						|
 | 
						|
  const fastify = Fastify({ exposeHeadRoutes: true })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/more-coffee',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      reply.send({ here: 'is coffee' })
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/some-light',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      reply.send('Get some light!')
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/more-coffee'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'application/json; charset=utf-8')
 | 
						|
    t.same(res.body, '')
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/some-light'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'text/plain; charset=utf-8')
 | 
						|
    t.equal(res.body, '')
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('Creates a HEAD route for a GET one with prefixTrailingSlash', async (t) => {
 | 
						|
  t.plan(1)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  const arr = []
 | 
						|
  fastify.register((instance, opts, next) => {
 | 
						|
    instance.addHook('onRoute', (routeOptions) => {
 | 
						|
      arr.push(`${routeOptions.method} ${routeOptions.url}`)
 | 
						|
    })
 | 
						|
 | 
						|
    instance.route({
 | 
						|
      method: 'GET',
 | 
						|
      path: '/',
 | 
						|
      exposeHeadRoute: true,
 | 
						|
      prefixTrailingSlash: 'both',
 | 
						|
      handler: (req, reply) => {
 | 
						|
        reply.send({ here: 'is coffee' })
 | 
						|
      }
 | 
						|
    })
 | 
						|
 | 
						|
    next()
 | 
						|
  }, { prefix: '/v1' })
 | 
						|
 | 
						|
  await fastify.ready()
 | 
						|
 | 
						|
  t.ok(true)
 | 
						|
})
 | 
						|
 | 
						|
test('Will not create a HEAD route that is not GET', t => {
 | 
						|
  t.plan(11)
 | 
						|
 | 
						|
  const fastify = Fastify({ exposeHeadRoutes: true })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/more-coffee',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      reply.send({ here: 'is coffee' })
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/some-light',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      reply.send()
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'POST',
 | 
						|
    path: '/something',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      reply.send({ look: 'It is something!' })
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/more-coffee'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'application/json; charset=utf-8')
 | 
						|
    t.same(res.body, '')
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/some-light'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], undefined)
 | 
						|
    t.equal(res.headers['content-length'], '0')
 | 
						|
    t.equal(res.body, '')
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/something'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 404)
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('HEAD route should handle properly each response type', t => {
 | 
						|
  t.plan(25)
 | 
						|
 | 
						|
  const fastify = Fastify({ exposeHeadRoutes: true })
 | 
						|
  const resString = 'Found me!'
 | 
						|
  const resJSON = { here: 'is Johnny' }
 | 
						|
  const resBuffer = Buffer.from('I am a buffer!')
 | 
						|
  const resStream = stream.Readable.from('I am a stream!')
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/json',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      reply.send(resJSON)
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/string',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      reply.send(resString)
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/buffer',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      reply.send(resBuffer)
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/buffer-with-content-type',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      reply.headers({ 'content-type': 'image/jpeg' })
 | 
						|
      reply.send(resBuffer)
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/stream',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      return resStream
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/json'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'application/json; charset=utf-8')
 | 
						|
    t.equal(res.headers['content-length'], `${Buffer.byteLength(JSON.stringify(resJSON))}`)
 | 
						|
    t.same(res.body, '')
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/string'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'text/plain; charset=utf-8')
 | 
						|
    t.equal(res.headers['content-length'], `${Buffer.byteLength(resString)}`)
 | 
						|
    t.equal(res.body, '')
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/buffer'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'application/octet-stream')
 | 
						|
    t.equal(res.headers['content-length'], `${resBuffer.byteLength}`)
 | 
						|
    t.equal(res.body, '')
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/buffer-with-content-type'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'image/jpeg')
 | 
						|
    t.equal(res.headers['content-length'], `${resBuffer.byteLength}`)
 | 
						|
    t.equal(res.body, '')
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/stream'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'application/octet-stream')
 | 
						|
    t.equal(res.headers['content-length'], undefined)
 | 
						|
    t.equal(res.body, '')
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('HEAD route should respect custom onSend handlers', t => {
 | 
						|
  t.plan(6)
 | 
						|
 | 
						|
  let counter = 0
 | 
						|
  const resBuffer = Buffer.from('I am a coffee!')
 | 
						|
  const fastify = Fastify({ exposeHeadRoutes: true })
 | 
						|
  const customOnSend = (res, reply, payload, done) => {
 | 
						|
    counter = counter + 1
 | 
						|
    done(null, payload)
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/more-coffee',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      reply.send(resBuffer)
 | 
						|
    },
 | 
						|
    onSend: [customOnSend, customOnSend]
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/more-coffee'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'application/octet-stream')
 | 
						|
    t.equal(res.headers['content-length'], `${resBuffer.byteLength}`)
 | 
						|
    t.equal(res.body, '')
 | 
						|
    t.equal(counter, 2)
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('route onSend can be function or array of functions', t => {
 | 
						|
  t.plan(12)
 | 
						|
  const counters = { single: 0, multiple: 0 }
 | 
						|
 | 
						|
  const resBuffer = Buffer.from('I am a coffee!')
 | 
						|
  const fastify = Fastify({ exposeHeadRoutes: true })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/coffee',
 | 
						|
    handler: () => resBuffer,
 | 
						|
    onSend: (res, reply, payload, done) => {
 | 
						|
      counters.single += 1
 | 
						|
      done(null, payload)
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  const customOnSend = (res, reply, payload, done) => {
 | 
						|
    counters.multiple += 1
 | 
						|
    done(null, payload)
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/more-coffee',
 | 
						|
    handler: () => resBuffer,
 | 
						|
    onSend: [customOnSend, customOnSend]
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({ method: 'HEAD', url: '/coffee' }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'application/octet-stream')
 | 
						|
    t.equal(res.headers['content-length'], `${resBuffer.byteLength}`)
 | 
						|
    t.equal(res.body, '')
 | 
						|
    t.equal(counters.single, 1)
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({ method: 'HEAD', url: '/more-coffee' }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'application/octet-stream')
 | 
						|
    t.equal(res.headers['content-length'], `${resBuffer.byteLength}`)
 | 
						|
    t.equal(res.body, '')
 | 
						|
    t.equal(counters.multiple, 2)
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('no warning for exposeHeadRoute', async t => {
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/more-coffee',
 | 
						|
    exposeHeadRoute: true,
 | 
						|
    async handler () {
 | 
						|
      return 'hello world'
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  const listener = (w) => {
 | 
						|
    t.fail('no warning')
 | 
						|
  }
 | 
						|
 | 
						|
  process.on('warning', listener)
 | 
						|
 | 
						|
  await fastify.listen(0)
 | 
						|
 | 
						|
  process.removeListener('warning', listener)
 | 
						|
 | 
						|
  await fastify.close()
 | 
						|
})
 | 
						|
 | 
						|
test("HEAD route should handle stream.on('error')", t => {
 | 
						|
  t.plan(6)
 | 
						|
 | 
						|
  const resStream = stream.Readable.from('Hello with error!')
 | 
						|
  const logStream = split(JSON.parse)
 | 
						|
  const expectedError = new Error('Hello!')
 | 
						|
  const fastify = Fastify({
 | 
						|
    logger: {
 | 
						|
      stream: logStream,
 | 
						|
      level: 'error'
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/more-coffee',
 | 
						|
    exposeHeadRoute: true,
 | 
						|
    handler: (req, reply) => {
 | 
						|
      process.nextTick(() => resStream.emit('error', expectedError))
 | 
						|
      return resStream
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  logStream.once('data', line => {
 | 
						|
    const { message, stack } = expectedError
 | 
						|
    t.same(line.err, { type: 'Error', message, stack })
 | 
						|
    t.equal(line.msg, 'Error on Stream found for HEAD route')
 | 
						|
    t.equal(line.level, 50)
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/more-coffee'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'application/octet-stream')
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('HEAD route should not be exposed by default', t => {
 | 
						|
  t.plan(7)
 | 
						|
 | 
						|
  const resStream = stream.Readable.from('Hello with error!')
 | 
						|
  const resJson = { hello: 'world' }
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/without-flag',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      return resStream
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    exposeHeadRoute: true,
 | 
						|
    method: 'GET',
 | 
						|
    path: '/with-flag',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      return resJson
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/without-flag'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 404)
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/with-flag'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'application/json; charset=utf-8')
 | 
						|
    t.equal(res.headers['content-length'], `${Buffer.byteLength(JSON.stringify(resJson))}`)
 | 
						|
    t.equal(res.body, '')
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('HEAD route should be exposed if route exposeHeadRoute is set', t => {
 | 
						|
  t.plan(7)
 | 
						|
 | 
						|
  const resBuffer = Buffer.from('I am a coffee!')
 | 
						|
  const resJson = { hello: 'world' }
 | 
						|
  const fastify = Fastify({ exposeHeadRoutes: false })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    exposeHeadRoute: true,
 | 
						|
    method: 'GET',
 | 
						|
    path: '/one',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      return resBuffer
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/two',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      return resJson
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/one'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'application/octet-stream')
 | 
						|
    t.equal(res.headers['content-length'], `${resBuffer.byteLength}`)
 | 
						|
    t.equal(res.body, '')
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/two'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 404)
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('Set a custom HEAD route before GET one without disabling exposeHeadRoutes (global)', t => {
 | 
						|
  t.plan(6)
 | 
						|
 | 
						|
  const resBuffer = Buffer.from('I am a coffee!')
 | 
						|
  const fastify = Fastify({
 | 
						|
    exposeHeadRoutes: true
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'HEAD',
 | 
						|
    path: '/one',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      reply.header('content-type', 'application/pdf')
 | 
						|
      reply.header('content-length', `${resBuffer.byteLength}`)
 | 
						|
      reply.header('x-custom-header', 'some-custom-header')
 | 
						|
      reply.send()
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    path: '/one',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      return resBuffer
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/one'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'application/pdf')
 | 
						|
    t.equal(res.headers['content-length'], `${resBuffer.byteLength}`)
 | 
						|
    t.equal(res.headers['x-custom-header'], 'some-custom-header')
 | 
						|
    t.equal(res.body, '')
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('Set a custom HEAD route before GET one without disabling exposeHeadRoutes (route)', t => {
 | 
						|
  t.plan(7)
 | 
						|
 | 
						|
  function onWarning (code) {
 | 
						|
    t.equal(code, 'FSTDEP007')
 | 
						|
  }
 | 
						|
  const warning = {
 | 
						|
    emit: onWarning
 | 
						|
  }
 | 
						|
 | 
						|
  const route = proxyquire('../lib/route', { './warnings': warning })
 | 
						|
  const fastify = proxyquire('..', { './lib/route.js': route })()
 | 
						|
 | 
						|
  const resBuffer = Buffer.from('I am a coffee!')
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'HEAD',
 | 
						|
    path: '/one',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      reply.header('content-type', 'application/pdf')
 | 
						|
      reply.header('content-length', `${resBuffer.byteLength}`)
 | 
						|
      reply.header('x-custom-header', 'some-custom-header')
 | 
						|
      reply.send()
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    exposeHeadRoute: true,
 | 
						|
    path: '/one',
 | 
						|
    handler: (req, reply) => {
 | 
						|
      return resBuffer
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.inject({
 | 
						|
    method: 'HEAD',
 | 
						|
    url: '/one'
 | 
						|
  }, (error, res) => {
 | 
						|
    t.error(error)
 | 
						|
    t.equal(res.statusCode, 200)
 | 
						|
    t.equal(res.headers['content-type'], 'application/pdf')
 | 
						|
    t.equal(res.headers['content-length'], `${resBuffer.byteLength}`)
 | 
						|
    t.equal(res.headers['x-custom-header'], 'some-custom-header')
 | 
						|
    t.equal(res.body, '')
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('HEAD routes properly auto created for GET routes when prefixTrailingSlash: \'no-slash\'', t => {
 | 
						|
  t.plan(2)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(function routes (f, opts, next) {
 | 
						|
    f.route({
 | 
						|
      method: 'GET',
 | 
						|
      url: '/',
 | 
						|
      exposeHeadRoute: true,
 | 
						|
      prefixTrailingSlash: 'no-slash',
 | 
						|
      handler: (req, reply) => {
 | 
						|
        reply.send({ hello: 'world' })
 | 
						|
      }
 | 
						|
    })
 | 
						|
 | 
						|
    next()
 | 
						|
  }, { prefix: '/prefix' })
 | 
						|
 | 
						|
  fastify.inject({ url: '/prefix/prefix', method: 'HEAD' }, (err, res) => {
 | 
						|
    t.error(err)
 | 
						|
    t.equal(res.statusCode, 404)
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('HEAD routes properly auto created for GET routes when prefixTrailingSlash: \'both\'', async t => {
 | 
						|
  t.plan(3)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(function routes (f, opts, next) {
 | 
						|
    f.route({
 | 
						|
      method: 'GET',
 | 
						|
      url: '/',
 | 
						|
      exposeHeadRoute: true,
 | 
						|
      prefixTrailingSlash: 'both',
 | 
						|
      handler: (req, reply) => {
 | 
						|
        reply.send({ hello: 'world' })
 | 
						|
      }
 | 
						|
    })
 | 
						|
 | 
						|
    next()
 | 
						|
  }, { prefix: '/prefix' })
 | 
						|
 | 
						|
  const doublePrefixReply = await fastify.inject({ url: '/prefix/prefix', method: 'HEAD' })
 | 
						|
  const trailingSlashReply = await fastify.inject({ url: '/prefix/', method: 'HEAD' })
 | 
						|
  const noneTrailingReply = await fastify.inject({ url: '/prefix', method: 'HEAD' })
 | 
						|
 | 
						|
  t.equal(doublePrefixReply.statusCode, 404)
 | 
						|
  t.equal(trailingSlashReply.statusCode, 200)
 | 
						|
  t.equal(noneTrailingReply.statusCode, 200)
 | 
						|
})
 | 
						|
 | 
						|
test('Request and Reply share the route config', async t => {
 | 
						|
  t.plan(3)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  const config = {
 | 
						|
    this: 'is a string',
 | 
						|
    thisIs: function aFunction () {}
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.route({
 | 
						|
    method: 'GET',
 | 
						|
    url: '/',
 | 
						|
    config,
 | 
						|
    handler: (req, reply) => {
 | 
						|
      t.same(req.context, reply.context)
 | 
						|
      t.same(req.context.config, reply.context.config)
 | 
						|
      t.match(req.context.config, config, 'there are url and method additional properties')
 | 
						|
 | 
						|
      reply.send({ hello: 'world' })
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  await fastify.inject('/')
 | 
						|
})
 | 
						|
 | 
						|
test('Will not try to re-createprefixed HEAD route if it already exists and exposeHeadRoutes is true', async (t) => {
 | 
						|
  t.plan(1)
 | 
						|
 | 
						|
  const fastify = Fastify({ exposeHeadRoutes: true })
 | 
						|
 | 
						|
  fastify.register((scope, opts, next) => {
 | 
						|
    scope.route({
 | 
						|
      method: 'HEAD',
 | 
						|
      path: '/route',
 | 
						|
      handler: (req, reply) => {
 | 
						|
        reply.header('content-type', 'text/plain')
 | 
						|
        reply.send('custom HEAD response')
 | 
						|
      }
 | 
						|
    })
 | 
						|
    scope.route({
 | 
						|
      method: 'GET',
 | 
						|
      path: '/route',
 | 
						|
      handler: (req, reply) => {
 | 
						|
        reply.send({ ok: true })
 | 
						|
      }
 | 
						|
    })
 | 
						|
 | 
						|
    next()
 | 
						|
  }, { prefix: '/prefix' })
 | 
						|
 | 
						|
  await fastify.ready()
 | 
						|
 | 
						|
  t.ok(true)
 | 
						|
})
 | 
						|
 | 
						|
test('Correct error message is produced if "path" option is used', t => {
 | 
						|
  t.plan(2)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  t.throws(() => {
 | 
						|
    fastify.route({
 | 
						|
      method: 'GET',
 | 
						|
      path: '/test'
 | 
						|
    })
 | 
						|
  }, new Error('Missing handler function for GET:/test route.'))
 | 
						|
 | 
						|
  t.throws(() => {
 | 
						|
    fastify.route({
 | 
						|
      method: 'POST',
 | 
						|
      url: '/test',
 | 
						|
      handler: function () {},
 | 
						|
      errorHandler: ''
 | 
						|
    })
 | 
						|
  }, new Error('Error Handler for POST:/test route, if defined, must be a function'))
 | 
						|
})
 | 
						|
 | 
						|
test('invalid url attribute - non string URL', t => {
 | 
						|
  t.plan(1)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  try {
 | 
						|
    fastify.get(/^\/(donations|skills|blogs)/, () => {})
 | 
						|
  } catch (error) {
 | 
						|
    t.equal(error.code, FST_ERR_INVALID_URL().code)
 | 
						|
  }
 | 
						|
})
 |