@fastify/static

repository·main·Indexed 19 days ago

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

A high-performance plugin for serving static files within a Fastify application. It provides features such as custom URL prefixes, directory listing, pre-compressed asset serving (.br, .gz), and Cache-Control management. The plugin decorates the Fastify Reply object with `sendFile` and `download` methods for manual file delivery.

Tokens
3.2K
Snippets
11
Records
15
Agent score
18%

What's inside @fastify/static

  1. Enable pre-compressed asset serving

    main
    Setting preCompressed: true allows the plugin to serve Brotli (.br) or Gzip (.gz) versions of files if the client's Accept-Encoding header supports them. The plugin will look for these files as siblings to the original file (e.g., main.js.br for main.js). This setting automatically adds a Vary: Accept-Encoding header.
  2. Register multiple prefixed roots

    main

    You can register the plugin multiple times to serve different directories under different URL prefixes. Note that if you register the plugin multiple times, you should set decorateReply: false on subsequent registrations to avoid errors, as the reply.sendFile decorator is added by the first registration.

    const fastify = require('fastify')()
    const fastifyStatic = require('@fastify/static')
    const path = require('node:path')
    
    // first plugin
    fastify.register(fastifyStatic, {
      root: path.join(__dirname, 'public')
    })
    
    // second plugin
    fastify.register(fastifyStatic, {
      root: path.join(__dirname, 'node_modules'),
      prefix: '/node_modules/',
      decorateReply: false // the reply decorator has been added by the first plugin registration
    })
  3. Basic usage of @fastify/static

    main

    Register @fastify/static to serve files from a specific directory. By default, files are served from the root directory at the / prefix. You can use reply.sendFile(path) to serve specific files within your route handlers.

    const fastify = require('fastify')({logger: true})
    const path = require('node:path')
    
    fastify.register(require('@fastify/static'), {
      root: path.join(__dirname, 'public'),
      prefix: '/public/', // optional: default '/'
    })
    
    fastify.get('/another/path', function (req, reply) {
      reply.sendFile('myHtml.html') // serving path.join(__dirname, 'public', 'myHtml.html') directly
    })
    
    fastify.listen({ port: 3000 }, (err, address) => {
      if (err) throw err
    })
  4. Handle 404s in encapsulated contexts

    main

    When using @fastify/static inside an encapsulated context (e.g., via fastify.register with a scope), you may need to set wildcard: false to ensure that index resolution and nested setNotFoundHandler calls work correctly for files within that scope.

    const app = require('fastify')();
    
    app.register((childContext, _, done) => {
        childContext.register(require('@fastify/static'), {
            root: path.join(__dirname, 'docs'),
            wildcard: false
        });
        childContext.setNotFoundHandler((_, reply) => {
            return reply.code(404).type('text/html').sendFile('404.html');
        });
        done();
    }, { prefix: 'docs' });
  5. Manage Cache-Control headers for static assets

    main

    You can manage caching behavior globally via plugin options or per-request via reply.sendFile or reply.download options. This is particularly useful for Single Page Applications (SPAs) where immutable assets (like hashed JS/CSS) can have long maxAge values, while index.html should have maxAge: 0 to prevent caching.

    // Global configuration for immutable assets
    fastify.register(require('@fastify/static'), {
      root: path.join(import.meta.dirname, 'dist'),
      maxAge: '30d',
      immutable: true,
    })
    
    // Per-request override for non-cacheable files
    fastify.get('/', function (req, reply) {
      reply.sendFile('index.html', {maxAge: 0, immutable: false})
    })
  6. Configure directory listing with the `list` option

    main

    The list option allows you to serve a directory listing. You can specify the format (json or html) and a render function if using HTML. If using json, you can control the detail level via list.jsonFormat (names or extended).

    fastify.register(require('@fastify/static'), {
      root: path.join(__dirname, '/static'),
      prefix: '/public',
      prefixAvoidTrailingSlash: true,
      list: {
        format: 'json',
        names: ['index', 'index.json', '/']
      }
    })
  7. Configure @fastify/static plugin options

    main

    The following options are available when registering the plugin:

    • serve (default: true): If false, the plugin will not serve files from the root directory.
    • root (required if serve is not false): The absolute path of the directory containing the files to serve. Can be an array of directories for priority-based serving.
    • prefix (default: '/'): URL path prefix for the static directory.
    • constraints (default: {}): Fastify route constraints.
    • logLevel (default: 'info'): Log level for registered routes.
    • prefixAvoidTrailingSlash (default: false): If true, no trailing "/" is added to the prefix.
    • schemaHide (default: true): Whether to hide the fastify route hide-schema attribute.
    • setHeaders (default: undefined): A synchronous function fn(reply, path, stat) to set custom headers.
    • redirect (default: false): If true, redirects to the directory with a trailing slash.
    • wildcard (default: true): If true, uses a wildcard route. If false, globs the filesystem for routes.
    • globIgnore (default: undefined): Passed to glob as the ignore option when wildcard is false.
    • allowedPath (default: (pathName, root, request) => true): Function to filter served files. Returning false triggers a 404.
    • index (default: undefined): Supports "index.html" by default. Can be set to false or a custom string/array.
    • serveDotFiles (default: false): If true, serves files in hidden directories (e.g., .foo).
    • list (default: undefined): If set, provides a directory list (JSON or HTML).
    • preCompressed (default: false): Tries to serve .br or .gz variants if supported by Accept-Encoding.
    • suppressWarning (default: false): If true, suppresses plugin warnings.
    • decorateReply (default: true): Whether to add sendFile and download to the reply object.
  8. Register @fastify/static as a plugin

    main

    To serve static files in your Fastify application, register the @fastify/static plugin. You must provide a root option, which can be a single absolute path string, an array of absolute path strings, or a file:// URL.

    By default, the plugin serves files under the / prefix. You can customize this using the prefix option.

    const fastify = require('fastify')()
    const fastifyStatic = require('@fastify/static')
    
    fastify.register(fastifyStatic, {
      root: path.join(__dirname, 'public'),
      prefix: '/static',
    })
  9. Download a file with a custom filename

    main

    Use reply.download(path, filename) to send a file and set the Content-Disposition header with a custom filename. This is useful for forcing a download with a specific name.

    fastify.get('/download', function (req, reply) {
      reply.download('myHtml.html', 'custom-filename.html')
    })
  10. Configure @fastify/static options

    main

    The following options can be passed to the fastifyStatic plugin during registration:

    OptionTypeDefaultDescription
    rootstringrequiredAbsolute path to the directory containing static files. Can be an array of paths.
    prefixstring'/'The URL prefix for the static files.
    servebooleantrueIf false, the plugin will not automatically register routes for static files.
    wildcardbooleantrueIf true, uses a wildcard route (prefix/*) to match files. If false, it explicitly registers routes for every file found in the root.
    indexstring | string[]['index.html']Files to use as directory indexes.
    dotfiles'allow' | 'deny' | 'ignore''allow'Controls how files starting with a dot are handled.
    preCompressedbooleanfalseIf true, the plugin will attempt to serve pre-compressed files (e.g., .br, .gz, .deflate) based on the Accept-Encoding header.
    listbooleanfalseIf true, enables directory listing when a directory is requested.
    redirectbooleanfalseIf true, enables redirects (e.g., adding trailing slashes to directory requests).
    setHeadersfunctionundefinedA function called to set custom headers on the response. Signature: (reply, filePath, stat)
    schemaHidebooleantrueIf true, hides the static routes from the Fastify schema.
    allowedPathfunctionundefinedA function to validate if a requested path is allowed. Signature: (pathname, root, request)
  11. Reference error codes for @fastify/static

    main

    Errors thrown by the plugin can be caught and identified using the errors object exported from @fastify/static.

    CodeReason
    FST_STATIC_INVALID_OPTIONOption is invalid or missing.
    FST_STATIC_INVALID_OPTION_VALUEOption provided with unsupported type.
    FST_STATIC_MULTIROOT_LIST_CONFLICTMulti root and list option cannot be used together.
    FST_STATIC_INVALID_REDIRECT_URLCannot redirect to the provided URL.
    const { errors } = require('@fastify/static')