Michael Herman

Software Developer

Swagger and NodeJS

This tutorial details how to describe a RESTFul API using Swagger along with Node and Express.

node swagger api


By the end of this tutorial, you will be able to…

  1. Describe the purpose of Swagger
  2. Generate a Swagger Spec based on an existing RESTful API developed with Node, Express, and Postgres
  3. Set up the Swagger UI for testing and interacting with the API

Swagger

Swagger is a specification for describing, producing, consuming, testing, and visualizing a RESTful API. It provides a number of tools for automatically generating documentation based on a given endpoint.

Now when you make changes to your code, your documentation is updated and synchronized with the API so that consumers can quickly learn which resources are available, how to access them, and what to expect (status code, content-type, etc.) when interacting with the various endpoints.

Getting Started

Starting a New Project

If you’re starting a new project, you can easily generate the Swagger Specification and project boilerplate using the Swagger Editor. Test it out here.

If you don’t like the generated project structure, you can just export the JSON (or YAML) spec file and then use a custom generator, like Swaggerize Express, to generate the boilerplate. Then when you need to make changes to the API, you can just update the spec file. Simple.

Updating an Existing Project

For this tutorial, we will be generating the Swagger spec based on the code from a previously created project that has the following RESTful endpoints:

URL HTTP Verb Action
/api/puppies GET Return ALL puppies
/api/puppies/:id GET Return a SINGLE puppy
/api/puppies POST Add a puppy
/api/puppies/:id PUT Update a puppy
/api/puppies/:id DELETE Delete a puppy

Clone down the project:

1
2
3
4
$ git clone https://github.com/mjhea0/node-postgres-promises.git node-swagger-api
$ cd node-swagger-api
$ git checkout tags/v1 -b swagger
$ npm install

Want to learn how this project was created? Check out the Designing a RESTful API With Node and Postgres post.

This project uses Postgres, so run create the database and apply the schema:

1
$ psql -f puppies.sql

Run the server, and then navigate to http://localhost:3000/api/puppies in your browser of choice. You should see:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
  status: "success",
  data: [
    {
      id: 1,
      name: "Tyler",
      breed: "Shih-tzu",
      age: 3,
      sex: "M"
    }
  ],
  message: "Retrieved ALL puppies"
}

Test out each endpoint to make sure everything works before moving on.

Generating the Swagger Spec

To generate the Swagger specification, we will be using swagger-jsdoc.

Install swagger-jsdoc:

1
$ npm install swagger-jsdoc@1.3.0 --save

Add the requirement to app.js:

1
var swaggerJSDoc = require('swagger-jsdoc');

Then add the following code to app.js just below var app = express();:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// swagger definition
var swaggerDefinition = {
  info: {
    title: 'Node Swagger API',
    version: '1.0.0',
    description: 'Demonstrating how to describe a RESTful API with Swagger',
  },
  host: 'localhost:3000',
  basePath: '/',
};

// options for the swagger docs
var options = {
  // import swaggerDefinitions
  swaggerDefinition: swaggerDefinition,
  // path to the API docs
  apis: ['./routes/*.js'],
};

// initialize swagger-jsdoc
var swaggerSpec = swaggerJSDoc(options);

Take note of the comments above. This code essentially initializes swagger-jsdoc and adds the appropriate metadata to the Swagger specification.

Add the route to serve up the Swagger spec:

1
2
3
4
5
// serve swagger
app.get('/swagger.json', function(req, res) {
  res.setHeader('Content-Type', 'application/json');
  res.send(swaggerSpec);
});

Fire up the server and navigate to http://localhost:3000/swagger.json to see the basic spec:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  info: {
    title: "Node Swagger API",
    version: "1.0.0",
    description: "Demonstrating how to describe a RESTful API with Swagger"
  },
  host: "localhost:3000",
  basePath: "/",
  swagger: "2.0",
  paths: { },
  definitions: { },
  responses: { },
  parameters: { },
  securityDefinitions: { }
}

Now we need to update the routes…

Updating the Route Handlers

swagger-jsdoc uses JSDoc-style comments to generate the Swagger spec. So, add such comments, in YAML, to the route handlers that describe their functionality.

GET ALL

Add the comments in /routes/index.js just above the handler, like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
 * @swagger
 * /api/puppies:
 *   get:
 *     tags:
 *       - Puppies
 *     description: Returns all puppies
 *     produces:
 *       - application/json
 *     responses:
 *       200:
 *         description: An array of puppies
 *         schema:
 *           $ref: '#/definitions/Puppy'
 */
router.get('/api/puppies', db.getAllPuppies);

This should be fairly self-explanatory. We have an /api/puppies endpoint that returns a 200 response to a GET request. The $ref is used to re-use definitions to keep the code DRY.

Add the following code above the previous code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
 * @swagger
 * definition:
 *   Puppy:
 *     properties:
 *       name:
 *         type: string
 *       breed:
 *         type: string
 *       age:
 *         type: integer
 *       sex:
 *         type: string
 */

Now we can use that definition for each of the HTTP methods.

For more information and examples, please see the Swagger Specification.

GET Single

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * @swagger
 * /api/puppies/{id}:
 *   get:
 *     tags:
 *       - Puppies
 *     description: Returns a single puppy
 *     produces:
 *       - application/json
 *     parameters:
 *       - name: id
 *         description: Puppy's id
 *         in: path
 *         required: true
 *         type: integer
 *     responses:
 *       200:
 *         description: A single puppy
 *         schema:
 *           $ref: '#/definitions/Puppy'
 */

POST

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * @swagger
 * /api/puppies:
 *   post:
 *     tags:
 *       - Puppies
 *     description: Creates a new puppy
 *     produces:
 *       - application/json
 *     parameters:
 *       - name: puppy
 *         description: Puppy object
 *         in: body
 *         required: true
 *         schema:
 *           $ref: '#/definitions/Puppy'
 *     responses:
 *       200:
 *         description: Successfully created
 */

PUT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 * @swagger
 * /api/puppies/{id}:
 *   put:
 *     tags: Puppies
 *     description: Updates a single puppy
 *     produces: application/json
 *     parameters:
 *       name: puppy
 *       in: body
 *       description: Fields for the Puppy resource
 *       schema:
 *         type: array
 *         $ref: '#/definitions/Puppy'
 *     responses:
 *       200:
 *         description: Successfully updated
 */

DELETE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 * @swagger
 * /api/puppies/{id}:
 *   delete:
 *     tags:
 *       - Puppies
 *     description: Deletes a single puppy
 *     produces:
 *       - application/json
 *     parameters:
 *       - name: id
 *         description: Puppy's id
 *         in: path
 *         required: true
 *         type: integer
 *     responses:
 *       200:
 *         description: Successfully deleted
 */

Check out the updated spec at http://localhost:3000/swagger.json.

Adding Swagger UI

Finally, download the Swagger UI repo, add the “dist” folder from the downloaded repo to the “public” folder in the project directory, and then rename the directory to “api-docs”.

Now within index.html inside the “api-docs” directory just update this line-

1
url = "http://petstore.swagger.io/v2/swagger.json";

To-

1
url = "http://localhost:3000/swagger.json";

Finally, navigate to http://localhost:3000/api-docs/ in your browser to test out the API endpoints:

Swagger UI




Download the code from the repo. Cheers!

Comments