Swagger: Time to document that Express API you built!

Alexander Karan
25/5/2019 | 6 min read

So you have built a restful API but without documentation, does it even exist? I love creating API’s with ExpressJS but documenting them is a pain in the ass until I found “swagger-ui-express” and “swagger-jsdoc.”



Now Swagger has some fantastic documentation but wasn’t so straightforward when setting up with express, so let’s jump straight into it and document our API.

Before you start coding download the example project, I have created for you at:

The example project includes two primary routes one to get users and another to create a user. I have not connected any database, so I have created functions in the GET and POST requests to simulate this.

Fair warning do not use any of this app in production; it’s merely to help you understand how to use Swagger with ExpressJS.

First, we need to add our frameworks for this project using npm.

npm install
npm install swagger-ui-express --save
npm install swagger-jsdoc --save

Swagger-ui-express adds middleware to our Express app and renders some beautiful UI for our docs while swagger-jsdoc allows us to document our API using JSDoc by adding a swagger tag to our comment block. Let’s configure our API docs, so they render at the end point of api/v1/docs.

Go to ./Routes/index.js and add a requirement for our two modules at the top of the file:

const swaggerJsdoc = require(“swagger-jsdoc”);
const swaggerUi = require(“swagger-ui-express”);

Now under

router.get("/users", (req, res, next) => {
   const userOne = new User("Alexander", "[email protected]");
   const userTwo = new User("Ryan", "[email protected]");
   res.json({ userOne, userTwo });
});

add your Swagger setup, copy the provided code example in and then lets run through it.

To start with, I have defined my options for the Swagger set up focusing on two primary keys swaggerDefinition and apis, for now, you can leave the apis key with an empty array, there are more options than this and I encourage you to read the Swagger docs and to check them out.

The swaggerDefinition needs a few key components, so let run through them:

  • openapi: The version of Open API we are using, for this set up I am using 3.0.0
  • info: This covers the necessary information on your API and is optional field
    • info.title: Title for your API
    • info.version: The version of the API
    • info.decsription: A detailed summary of the API
    • info.license: Details about the license your API is under
    • info.contact: Contact information for support using your API
  • servers: This takes an array of your base URLs for the API, meaning you can display the base URL for dev and production, it’s the simple things like this that make you love a framework.

Next, we assign the options and which generate the documentation spec from them. Then assign SwaggerUI to an endpoint using a router and calling:

const specs = swaggerJsdoc(options);
router.use("/docs", swaggerUi.serve);

As you can see I am rendering my docs at the endpoint /docs so on top of my base API URL that makes the full path to my docs:

localhost:3000/api/v1/docs

So final we add a get request to return the SwaggerUI generated docs. For a bonus I have added in the explorer option, this renders a search bar in our docs.

router.get("/docs", swaggerUi.setup(specs, { explorer: true }));

Right let spin up the server and check out the docs. I am using Nodemon so just cd into the example project and run:

nodemon index.js

Head to localhost:3000/api/v1/docs and you should see the following:



Looks pretty dam good but there is no documented models or routes yet so let changes that. Head to User.js and add in the following Code:

Let break down what’s happening here, first I have added the tag @swagger, so the comment block gets picked up, then I have filed this model under components and then schemas. Next, we define the name for the model in this case “User.” Now we add the real info; first, let’s mark what variables are required, then I provide the properties and what type they are with an optional description. I then finish it off with an example you will see why later. I highly recommend you read the Swagger Docs for the all options available when defining schemas here:

Head back to the index.js file in the Routes folder and add the following into the API array:

"./Models/User.js"

As we are using Nodemon if we hit save our server will reset, so head back to the browser and hit refresh and we should now see our User model.



Now let document our routes, so head back to the index.js file again in routes and copy in this bit of Code above the post request:

Once again, let’s break down what is happening here. My comment block needs to start with the @swagger block. Defining a Tag called User basically, this means any route comments I assign the User Tag to will appear under it in the documentation.

In the route comment block, you first need to define the path, then what type of request, e.g. post or get, add a summary and then a tag. Next, we add parameters and request bodies. In this simple example, we do not have any query or path parameters, so we only need to add a request body. First, I inform you that the request body is required, what content type it is in my case JSON and then a definition of a schema and an example. As I have already created this earlier in the User.js file I can simply add a reference to my User model using:

$ref: '#/components/schemas/User'

We finish with the response, which gives the option to add errors, but for this example, I am going to focus on the success response. First, I attach a description and content. Then once again, I can make things easy and reference the User model.

Now if we add the file path to the routes file into the API array in the Swagger options and hit save, it will update our docs. See my updated Swagger options:

Head over to the browser and hit refresh, and you should see the following:



It gets even better Swagger UI allows us to call documented requests inside the browser by hitting “Try it out”.

Now let’s add in the GET request, the only difference here is I change the request type to GET, remove the request body section and update the description.

Hit save and head over to the browser hit refresh, and you should see the following:



See how simple that whole process was, the reusability of Schemas/Models by using #ref makes it very easy to write your docs for the API. Examples of requests and responses can be created and shared using the #ref. I highly encourage you to read further about request and response components in the Swagger Docs:

If you switch branches on the example project to finishedProject you should see my finished work.

I hope you found this helpful and feel free to reach out to me on Twitter if you want some further help.

@alexanderk_ios