@fastify/sensible

repository·main·Indexed 19 days ago

https://github.com/fastify/fastify-sensible

A Fastify plugin providing sensible defaults and utilities, including HTTP error constructors (4xx and 5xx), Cache-Control header helpers, and request/reply decorations. It features fastify.assert for condition validation, fastify.to for async/await error handling without try-catch blocks, and utilities for managing forwarded client information and content-type checks.

Tokens
5.4K
Snippets
24
Records
26
Agent score
69%

What's inside @fastify/sensible

  1. Register @fastify/sensible in Fastify

    main

    To use the utilities, register the plugin with your Fastify instance. Once registered, the plugin decorates the fastify, reply, and request objects with various helper methods.

    const fastify = require('fastify')()
    fastify.register(require('@fastify/sensible'))
    
    fastify.get('/', (req, reply) => {
      reply.notFound()
    })
    
    fastify.listen({ port: 3000 })
  2. Manage Cache-Control headers with @fastify/sensible

    main

    The @fastify/sensible plugin decorates the Fastify reply object with several utility methods to manage HTTP Cache-Control headers. These methods allow you to set caching policies such as preventing caching, setting max-age, or configuring stale-while-revalidate behaviors. Most methods are chainable and return the reply object.

    // Example of chaining cache utilities on the reply object
    reply
      .maxAge('1h')
      .cacheControl('public')
      .header('X-Custom-Header', 'value')
  3. Configure a shared JSON Schema for HTTP errors

    main

    By setting the sharedSchemaId option during registration, you can add a shared JSON Schema to your Fastify instance. This allows you to use $ref in your route schemas to validate error response formats consistently.

    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 })
  4. Register @fastify/sensible plugin

    main

    To use @fastify/sensible, register it as a plugin in your Fastify instance. It decorates the Fastify instance, the Request object, and the Reply object with various utilities for error handling, assertions, and HTTP header management.

    If you want to use a shared JSON schema for HTTP errors across your application, you can pass sharedSchemaId in the plugin options.

    const Fastify = require('fastify')
    const fastifySensible = require('@fastify/sensible')
    
    const fastify = Fastify()
    
    fastify.register(fastifySensible, { sharedSchemaId: 'mySharedErrorSchema' })
    
    fastify.listen({ port: 3000 })
  5. Validate conditions with fastify.assert

    main

    The fastify.assert method verifies a condition. If the condition is falsy, it throws the specified HTTP error. This is particularly useful in async routes to avoid manual if/throw blocks.

    It also provides assertion utilities for testing or logic:

    • ok()
    • equal()
    • notEqual()
    • strictEqual()
    • notStrictEqual()
    • deepEqual()
    • notDeepEqual()
    // Throws a 400 error if authorization header is missing
    fastify.assert(
      req.headers.authorization, 400, 'Missing authorization header'
    )
  6. Use reply.vary and request helpers

    main

    The reply and request objects are decorated with utilities from jshttp/vary, jshttp/forwarded, and jshttp/type-is.

    // reply.vary: Add Vary header
    reply.vary('Accept')
    
    // request.forwarded: Check forwarded headers
    const forwarded = req.forwarded()
    
    // request.is: Check content type
    const isJson = req.is(['html', 'json'])
  7. Manage Cache-Control headers with reply helpers

    main

    The reply object is decorated with several helpers to easily manage HTTP caching headers.

    // Set specific cache control types
    reply.cacheControl('public')
    reply.cacheControl('immutable')
    
    // Set max-age (supports numbers or strings like '1d')
    reply.cacheControl('max-age', 42)
    reply.cacheControl('max-age', '1d')
    
    // Prevent caching (no-store, max-age=0, private + Pragma/Expires)
    reply.preventCache()
    
    // Revalidate (max-age=0, must-revalidate)
    reply.revalidate()
    
    // Static cache (public, max-age=N, immutable)
    reply.staticCache(42)
    
    // Stale content (RFC 5861)
    reply.stale('while-revalidate', 42)
    reply.stale('if-error', 1)
    
    // Set max-age (often used with reply.stale)
    reply.maxAge(86400)
  8. Handle async errors with fastify.to

    main

    The fastify.to method is an async/await wrapper inspired by await-to-js. It allows you to handle errors without using try-catch blocks by returning an array containing [error, result].

    const [err, user] = await fastify.to(
      db.findOne({ user: 'tyrion' })
    )
    
    if (err) {
      // handle error
    }
  9. Use fastify.httpErrors to create error objects

    main

    The fastify.httpErrors object provides constructors for all 4xx and 5xx HTTP errors. These follow the http-errors pattern and can be used to throw errors in async handlers or pass them to reply.send().

    Example usage:

    const notFoundErr = fastify.httpErrors.notFound('custom message')
    const err = fastify.httpErrors.createError(404, 'This video does not exist!')
  10. Reference: fastify.httpErrors 4xx and 5xx constructors

    main

    The following methods are available on fastify.httpErrors to generate specific HTTP error objects. A custom message is optional.

    4xx:
    - badRequest()
    - unauthorized()
    - paymentRequired()
    - forbidden()
    - notFound()
    - methodNotAllowed()
    - notAcceptable()
    - proxyAuthenticationRequired()
    - requestTimeout()
    - conflict()
    - gone()
    - lengthRequired()
    - preconditionFailed()
    - payloadTooLarge()
    - uriTooLong()
    - unsupportedMediaType()
    - rangeNotSatisfiable()
    - expectationFailed()
    - imateapot()
    - misdirectedRequest()
    - unprocessableEntity()
    - locked()
    - failedDependency()
    - tooEarly()
    - upgradeRequired()
    - preconditionRequired()
    - tooManyRequests()
    - requestHeaderFieldsTooLarge()
    - unavailableForLegalReasons()
    
    5xx:
    - internalServerError()
    - notImplemented()
    - badGateway()
    - serviceUnavailable()
    - gatewayTimeout()
    - httpVersionNotSupported()
    - variantAlsoNegotiates()
    - insufficientStorage()
    - loopDetected()
    - bandwidthLimitExceeded()
    - notExtended()
    - networkAuthenticationRequired()
  11. Use the `to` utility for promise error handling

    main

    The plugin decorates the Fastify instance with a to method. This is a utility that wraps a Promise and returns a tuple [error, data], allowing you to handle errors without using try/catch blocks (similar to Go's error handling pattern).

    • If the promise resolves: returns [null, data]
    • If the promise rejects: returns [err, undefined]
    fastify.get('/data', async (request, reply) => {
      const [err, data] = await fastify.to(someAsyncOperation())
    
      if (err) {
        return reply.sensibleInternalServerError(err.message)
      }
    
      return data
    })