@fastify/swagger-ui

repository·main·Indexed 41 days ago

https://github.com/fastify/fastify-swagger-ui

A Fastify plugin used to serve the Swagger UI documentation interface, allowing developers to visualize and interact with their API specifications. It requires @fastify/swagger as a dependency and provides configuration options for route prefixes, UI themes, custom logos, and authentication hooks via uiHooks.

Tokens
5.7K
Snippets
9
Records
14
Agent score
2%

What's inside fastify-swagger-ui

  1. Handle reverse proxies with indexPrefix

    main

    If your Fastify server is behind a reverse proxy (like NGINX) that uses path-based routing (e.g., serving the app at /service), the absolute links to static assets might break.

    To fix this, set indexPrefix to the external path prefix used by the proxy.

    Example: If NGINX routes /service/documentation to your app, set indexPrefix: '/service'.

  2. Configure Swagger UI via uiConfig

    main

    The uiConfig option allows you to pass configuration directly to the underlying Swagger UI library. Note that functions provided in uiConfig are executed in the browser and cannot access backend code. You can access the Swagger UI instance via the ui variable (assigned to window.ui).

    Multiple Specifications

    To enable a dropdown for switching between multiple API definitions, use the urls option within uiConfig. Each URL must be reachable by the client.

    await fastify.register(require('@fastify/swagger-ui'), {
      uiConfig: {
        urls: [
          { url: '/documentation/json', name: 'Main API' },
          { url: '/documentation/openapi.yaml', name: 'Other API' }
        ],
        'urls.primaryName': 'Other API'
      }
    })
    const fastify = require('fastify')()
    
    await fastify.register(require('@fastify/swagger'))
    
    await fastify.register(require('@fastify/swagger-ui'), {
      uiConfig: {
        onComplete: function () {
          alert('ui has type of ' + typeof ui) // 'ui has type of object'
          alert('fastify has type of ' + typeof fastify) // 'fastify has type of undefined'
          alert('window has type of ' + typeof window) // 'window has type of object'
          alert('global has type of ' + typeof global) // 'global has type of undefined'
        }
      }
    })
  3. Protect documentation routes with authentication

    main

    Use the uiHooks option to apply Fastify hooks (like onRequest or preHandler) to the documentation routes. This allows you to protect the Swagger UI behind authentication plugins like @fastify/basic-auth.

    await fastify.register(require('@fastify/swagger-ui', {
      uiHooks: {
        onRequest: fastify.basicAuth
      }
    })
  4. Bundle Swagger UI static assets

    main

    When bundling your application, you must copy the Swagger UI static files from the plugin's node_modules directory to your distribution folder and set the baseDir option to point to that folder.

    Using esbuild

    import { build } from 'esbuild'
    import { copy } from 'esbuild-plugin-copy'
    
    await build({
      // ...
      plugins: [
        copy({
          resolveFrom: 'cwd',
          assets: {
            from: ['node_modules/@fastify/swagger-ui/static/*'],
            to: ['dist/static'],
          },
        }),
      ],
    })

    Using Docker

    COPY ./node_modules/@fastify/swagger-ui/static /app/static

    Configuration

    await fastify.register(require('@fastify/swagger-ui'), {
      baseDir: isDev ? undefined : path.resolve('static'),
    })
  5. Basic usage of @fastify/swagger-ui

    main

    To use @fastify/swagger-ui, you must first register @fastify/swagger in your project. Then, register @fastify/swagger-ui with your desired configuration options.

    Key configuration options include:

    • routePrefix: The URL path where the Swagger UI will be served.
    • uiConfig: Configuration for the Swagger UI interface (e.g., docExpansion, deepLinking).
    • uiHooks: Lifecycle hooks for the UI requests (onRequest, preHandler).
    • staticCSP: Boolean to enable static Content Security Policy.
    • transformStaticCSP: Function to transform the CSP header.
    • transformSpecification: Function to transform the Swagger/OpenAPI specification object.
    • transformSpecificationClone: Boolean to determine if the specification should be cloned before transformation.

    Security Note: When defining security in your route schemas, the key (e.g., apiKey) must match the name of the security scheme declared in components.securitySchemes (OpenAPI 3) or securityDefinitions (Swagger 2.0). The empty array [] represents scopes and is used for API key authentication.

    import fastify from 'fastify'
    
    const app = fastify()
    
    // 1. Register @fastify/swagger first
    await app.register(import('@fastify/swagger'))
    
    // 2. Register @fastify/swagger-ui
    await app.register(import('@fastify/swagger-ui'), {
      routePrefix: '/documentation',
      uiConfig: {
        docExpansion: 'full',
        deepLinking: false
      },
      uiHooks: {
        onRequest: function (request, reply, next) { next() },
        preHandler: function (request, reply, next) { next() }
      },
      staticCSP: true,
      transformStaticCSP: (header) => header,
      transformSpecification: (swaggerObject, request, reply) => { return swaggerObject },
      transformSpecificationClone: true
    })
    
    // 3. Define routes with schemas
    app.put('/some-route/:id', {
      schema: {
        description: 'post some data',
        tags: ['user', 'code'],
        summary: 'qwerty',
        params: {
          type: 'object',
          properties: {
            id: {
              type: 'string',
              description: 'user id'
            }
          }
        },
        body: {
          type: 'object',
          properties: {
            hello: { type: 'string' },
            obj: {
              type: 'object',
              properties: {
                some: { type: 'string' }
              }
            }
          }
        },
        response: {
          201: {
            description: 'Successful response',
            type: 'object',
            properties: {
              hello: { type: 'string' }
            }
          },
          default: {
            description: 'Default response',
            type: 'object',
            properties: {
              foo: { type: 'string' }
            }
          }
        },
        security: [
          {
            "apiKey": []
          }
        ]
      }
    }, (req, reply) => {})
    
    await app.ready()
  6. Customize the Swagger UI theme and logo

    main

    You can inject custom CSS, JavaScript, and favicons using the theme option. You can also override the top bar logo using the logo option.

    await fastify.register(require('@fastify/swagger-ui'), {
      logo: {
        type: 'image/png',
        content: Buffer.from('iVBOR...', 'base64'),
        href: '/documentation',
        target: '_blank'
      },
      theme: {
        title: 'My custom title',
        js: [
          { filename: 'special.js', content: 'alert("client javascript")' }
        ],
        css: [
          { filename: 'theme.css', content: '* { border: 1px red solid; }' }
        ],
        favicon: [
          {
            filename: 'favicon.png',
            rel: 'icon',
            sizes: '16x16',
            type: 'image/png',
            content: Buffer.from('iVBOR...', 'base64')
          }
        ]
      }
    })
  7. Transform the Swagger specification with transformSpecification

    main

    Use transformSpecification to modify the swagger document dynamically on every request (e.g., to change the host based on the request hostname).

    By default, the swaggerObject passed to this function is a deep clone (controlled by transformSpecificationClone: true). If you want to implement your own cloning or caching logic for performance, set transformSpecificationClone: false.

    const fastify = require('fastify')()
    const LRU = require('tiny-lru').lru
    const rfdc = require('rfdc')()
    
    await fastify.register(require('@fastify/swagger'))
    
    const swaggerLru = new LRU(1000)
    await fastify.register(require('@fastify/swagger-ui'), {
      transformSpecificationClone: false,
      transformSpecification: (swaggerObject, req, reply) => {
        if (swaggerLru.has(req.hostname)) {
          return swaggerLru.get(req.hostname)
        }
        const clonedSwaggerObject = rfdc(swaggerObject)
        clonedSwaggerObject.host = req.hostname
        swaggerLru.set(req.hostname, clonedSwaggerObject)
        return clonedSwaggerObject
      }
    })
  8. Configure @fastify/swagger-ui options

    main

    When registering @fastify/swagger-ui, you can provide an options object to customize the UI behavior, appearance, and routing.

    Available configuration keys:

    • routePrefix: (string) The URL prefix for the documentation routes. Defaults to /documentation.
    • uiConfig: (object) Configuration passed to the Swagger UI.
    • initOAuth: (object) Configuration for OAuth initialization in the UI.
    • uiHooks: (object) Hooks for the UI.
    • theme: (object) Theme configuration for the UI.
    • logo: (object) Custom logo configuration. If omitted, the default logo is used.
  9. Check @fastify/swagger-ui compatibility

    main

    Ensure your plugin and Fastify versions are compatible. Note that if a Fastify version is out of support, the corresponding plugin versions are also considered out of support.

    Plugin versionFastify versionSwagger Plugin Version
    ^5.x^5.x^9.x
    ^2.x^4.x^8.x
    ^1.x^4.x^8.x
  10. Register @fastify/swagger-ui with options

    main

    When registering the @fastify/swagger-ui plugin, you can provide several configuration options to customize the documentation interface, routing, and behavior.

    | Option             | Default         | Description                                                                                                                                                                                                                                       |
     | ------------------ | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
     | baseDir              | undefined       | Directory from which the Swagger UI static assets (served under `<routePrefix>/static/`) are loaded, instead of the `static` folder shipped with this plugin. Any other file in that directory is also served relative to `routePrefix`, e.g. spec files referenced via `$ref`. When not set, only the bundled Swagger UI assets are served. Provided value should be an absolute path without trailing slash. See [Bundling](#bundling). |
     | initOAuth            | {}              | Configuration options for [Swagger UI initOAuth](https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/).                                                                                                                                                            |
     | routePrefix          | '/documentation' | Overwrite the default Swagger UI route prefix.                                                                                                                                                                     |
     | indexPrefix          | ''              | External path prefix added to the asset links in the index page, for when the Fastify server is behind path based routing (e.g. NGINX). See [Running behind a reverse proxy](#running-behind-a-reverse-proxy).                                                                    |
     | staticCSP            | false           | Enable CSP header for static resources.                                                                                                                                                                            |
     | transformStaticCSP   | undefined       | Synchronous function to transform CSP header for static resources if the header has been previously set.                                                                                                                                          |
     | transformSpecification     | undefined       | Synchronous function to transform the swagger document.                                                                                                                                                            |
     | transformSpecificationClone| true            | Provide a deepcloned swaggerObject to transformSpecification                                                                                                                                                                                      |
     | uiConfig             | {}              | Configuration options for [Swagger UI](https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md).                                                                                                                        |
     | uiHooks              | {}              | Additional hooks for the documentation's routes. You can provide the `onRequest` and `preHandler` hooks with the same [route's options](https://fastify.dev/docs/latest/Reference/Routes/#routes-options) interface.                                                               |
     | theme                | {}              | Add custom JavaScript and CSS to the Swagger UI web page                                                                                                                                                                       |
     | logLevel             | info            | Allow to define route log level.                                                                                                                                                                                                    |
  11. Exposed documentation URLs

    main

    The plugin exposes the following endpoints (note: these use the configured routePrefix, default is /documentation):

    • '/documentation/json': The JSON object representing the API.
    • '/documentation/yaml': The YAML object representing the API.
    • '/documentation/': The Swagger UI interface.
    • '/documentation/*': External files that can be used via $ref.