Document Our Express API with the Swagger UI Express Library

John Au-Yeung - Jan 25 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

Documenting APIs is painful and tedious.

However, we can make our lives easier with the Swagger UI Express library if we’re using Express.

In this article, we’ll look at how to use the library to document our Express API.

Installation

We can install the package by running:

npm i swagger-ui-express
Enter fullscreen mode Exit fullscreen mode

Documenting Our Endpoints

We can document our endpoints by writing some code.

First, we add our swagger.json file by writing:

{
  "swagger": "2.0",
  "info": {
    "title": "some-app",
    "version": "Unknown"
  },
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/{id}": {
      "parameters": [
        {
          "name": "id",
          "required": true,
          "in": "path",
          "type": "string",
          "description": "some id"
        }
      ],
      "get": {
        "operationId": "routeWithId",
        "summary": "some route",
        "description": "some route",
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "examples": {
              "application/json": "{ foo: 1 }"
            }
          }
        }
      }
    },
    "/": {
      "parameters": [],
      "get": {
        "operationId": "anotherRoute",
        "summary": "another route",
        "description": "another route",
        "produces": [
          "application/json"
        ],
        "responses": {
          "202": {
            "description": "202 response",
            "examples": {
              "application/json": "{ foo: 'bar' }"
            }
          }
        }
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

It has all the information about the endpoints in our app.

The data includes the parameters required and the responses.

parameters has the parameters and responses has possible responses from the endpoint.

Then in our app file, we write:

index.js

const express = require('express');
const bodyParser = require('body-parser');
const swaggerUi = require('swagger-ui-express');
const swaggerDocument = require('./swagger.json');
const swaggerOptions = {
  swaggerOptions: {
    validatorUrl: null
  }
};

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument, swaggerOptions));

app.get('/', (req, res) => {
  res.json({ foo: 'bar' });
});

app.get('/:id', (req, res) => {
  res.json({ foo: req.params.id });
});

app.listen(3000, () => console.log('server started'));
Enter fullscreen mode Exit fullscreen mode

We require our swagger.json file and add the api-docs endpoint to show the document.

validatorUrl has the URL for Swagger’s validator for validating our document.

We just add:

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument, swaggerOptions));
Enter fullscreen mode Exit fullscreen mode

to add the endpoint and pass in the options for displaying the document.

The swaggerUi.setup method takes the document and options as arguments.

When we go to the /api-docs endpoint, we should see the Swagger interface and try requests with our app.

We can enter the ID for the /{id} endpoint and see the response after clicking Execute.

Custom CSS Styles

We can add custom CSS with the customCss property:

const express = require('express');
const bodyParser = require('body-parser');
const swaggerUi = require('swagger-ui-express');
const swaggerDocument = require('./swagger.json');
const swaggerOptions = {
  swaggerOptions: {
    validatorUrl: null,
  },
  customCss: '.swagger-ui .topbar { display: none }'
};

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument, swaggerOptions));

app.get('/', (req, res) => {
  res.json({ foo: 'bar' });
});

app.get('/:id', (req, res) => {
  res.json({ foo: req.params.id });
});

app.listen(3000, () => console.log('server started'));
Enter fullscreen mode Exit fullscreen mode

We hid the top bar with:

customCss: '.swagger-ui .topbar { display: none }'
Enter fullscreen mode Exit fullscreen mode

Load Swagger from URL

We can load the Swagger file from a URL with the url option:

const express = require('express');
const app = express();
const swaggerUi = require('swagger-ui-express');

const options = {
  swaggerOptions: {
    url: 'http://petstore.swagger.io/v2/swagger.json'
  }
}

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(null, options));
Enter fullscreen mode Exit fullscreen mode

We can load more than one file:

const express = require('express');
const app = express();
const swaggerUi = require('swagger-ui-express');

const options = {
  explorer: true,
  swaggerOptions: {
    urls: [
      {
        url: 'http://petstore.swagger.io/v2/swagger.json',
        name: 'Spec1'
      },
      {
        url: 'http://petstore.swagger.io/v2/swagger.json',
        name: 'Spec2'
      }
    ]
  }
}

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(null, options));
Enter fullscreen mode Exit fullscreen mode

Conclusion

We can document our Express API easily with the Swagger UI Express library.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .