Home

Awesome

@fastify/sensible

CI NPM version js-standard-style

Defaults for Fastify that everyone can agree on™.<br> This plugin adds some useful utilities to your Fastify instance, see the API section to learn more.

Why are these APIs here and not included with Fastify?<br> Because Fastify aims to be as small and focused as possible, every utility that is not essential should be shipped as a standalone plugin.

Install

npm i @fastify/sensible

Compatibility

Plugin versionFastify version
^6.x^5.x
^5.x^4.x
^4.x^3.x
^2.x^2.x
^1.x^1.x

Please note that if a Fastify version is out of support, then so are the corresponding version(s) of this plugin in the table above. See Fastify's LTS policy for more details.

Usage

const fastify = require('fastify')()
fastify.register(require('@fastify/sensible'))

fastify.get('/', (req, reply) => {
  reply.notFound()
})

fastify.get('/async', async (req, reply) => {
  throw fastify.httpErrors.notFound()
})

fastify.get('/async-return', async (req, reply) => {
  return reply.notFound()
})

fastify.listen({ port: 3000 })

Shared JSON Schema for HTTP errors

If you set the sharedSchemaId option, a shared JSON Schema is added and can be used in your routes.

const fastify = require('fastify')()
fastify.register(require('@fastify/sensible'), {
  sharedSchemaId: 'HttpError'
})

fastify.get('/async', {
  schema: {
    response: {
      404: { $ref: 'HttpError' }
    }
  },
  handler: async (req, reply) => {
    return reply.notFound()
  }
})

fastify.listen({ port: 3000 })

API

fastify.httpErrors

Object that exposes createError and all of the 4xx and 5xx error constructors.

Use of 4xx and 5xx error constructors follows the same structure as new createError[code || name]([msg])) in http-errors:

 // the custom message is optional
const notFoundErr = fastify.httpErrors.notFound('custom message')

4xx

5xx

createError

Use of createError follows the same structure as createError([status], [message], [properties]) in http-errors:

const err = fastify.httpErrors.createError(404, 'This video does not exist!')

reply.[httpError]

The reply interface is decorated with all of the functions declared above, using it is easy:

fastify.get('/', (req, reply) => {
  reply.notFound()
})

reply.vary

The reply interface is decorated with jshttp/vary, the API is the same, but you do not need to pass the res object.

fastify.get('/', (req, reply) => {
  reply.vary('Accept')
  reply.send('ok')
})

reply.cacheControl

The reply interface is decorated an helper to configure cache control response headers.

// configure a single type
fastify.get('/', (req, reply) => {
  reply.cacheControl('public')
  reply.send('ok')
})

// configure multiple types
fastify.get('/', (req, reply) => {
  reply.cacheControl('public')
  reply.cacheControl('immutable')
  reply.send('ok')
})

// configure a type time
fastify.get('/', (req, reply) => {
  reply.cacheControl('max-age', 42)
  reply.send('ok')
})

// the time can be defined as string
fastify.get('/', (req, reply) => {
  // all the formats of github.com/vercel/ms are supported
  reply.cacheControl('max-age', '1d') // will set to 'max-age=86400'
  reply.send('ok')
})

reply.preventCache

The reply interface is decorated with a helper to set the cache control header to a no caching configuration.

fastify.get('/', (req, reply) => {
  // will set cache-control to 'no-store, max-age=0, private'
  // and for HTTP/1.0 compatibility
  // will set pragma to 'no-cache' and expires to 0
  reply.preventCache()
  reply.send('ok')
})

reply.revalidate

The reply interface is decorated with a helper to set the cache control header to a no caching configuration.

fastify.get('/', (req, reply) => {
  reply.revalidate() // will set to 'max-age=0, must-revalidate'
  reply.send('ok')
})

reply.staticCache

The reply interface is decorated with a helper to set the cache control header to a public and immutable configuration.

fastify.get('/', (req, reply) => {
  // the time can be defined as a string
  reply.staticCache(42) // will set to 'public, max-age=42, immutable'
  reply.send('ok')
})

reply.stale

The reply interface is decorated with a helper to set the cache control header for stale content.

fastify.get('/', (req, reply) => {
  // the time can be defined as a string
  reply.stale('while-revalidate', 42)
  reply.stale('if-error', 1)
  reply.send('ok')
})

reply.maxAge

The reply interface is decorated with a helper to set max age of the response. It can be used in conjunction with reply.stale, see here.

fastify.get('/', (req, reply) => {
  // the time can be defined as a string
  reply.maxAge(86400)
  reply.stale('while-revalidate', 42)
  reply.send('ok')
})

request.forwarded

The request interface is decorated with jshttp/forwarded, the API is the same, but you do not need to pass the request object:

fastify.get('/', (req, reply) => {
  reply.send(req.forwarded())
})

request.is

The request interface is decorated with jshttp/type-is, the API is the same, but you do not need to pass the request object:

fastify.get('/', (req, reply) => {
  reply.send(req.is(['html', 'json']))
})

assert

Verify if a given condition is true, if not it throws the specified http error.<br> Useful if you work with async routes:

// the custom message is optional
fastify.assert(
  req.headers.authorization, 400, 'Missing authorization header'
)

The assert API also exposes the following methods:

to

Async await wrapper for easy error handling without try-catch, inspired by await-to-js:

const [err, user] = await fastify.to(
  db.findOne({ user: 'tyrion' })
)

Contributing

Do you feel there is some utility that everyone can agree on which is not present?<br> Open an issue and let's discuss it! Even better a pull request!

Acknowledgements

The project name is inspired by vim-sensible, an awesome package that if you use vim you should use too.

License

MIT Copyright © Tomas Della Vedova & Fastify collaborators