Swagger for Node.js HTTP API Design

RisingStack's services:

Node.js Experts

Learn more at risingstack.com

Sign up to our newsletter!

In this article:

Swagger is a simple yet powerful representation of your RESTful API. With the largest ecosystem of API tooling on the planet, thousands of developers are supporting Swagger in almost every modern programming language and deployment environment.

With a Swagger-enabled API, you get interactive documentation, client SDK generation and discoverability.

Swagger Basics

That sounds nice, doesn’t it? Let me explain it a little bit more: these kinds of API description languages help us – developers – to create a rich documentation for our services. Basically it is a way to tell the consumer (may it be a web frontend or a mobile app) how to use the API, what the endpoints are available to call, what are their exact return values. In this article, we are going to take a look how can you start using Swagger with Node.js today.

It is a contract between the backend and the front end developer, takes care of the dependency between the two sides. If the document changes, you can see that the API changed, and adapt to it quickly.

It might be a good approach to keep the document in a separate repo and open discussions about it with the consumers. This way you can make sure your that your users will be satisfied with the structure of your API. It can be a source of conflicts but also can help to handle them.

Here at RisingStack we started to use this approach on a much higher level, but the credit goes to the KrakenJS team who have done so much work creating a swaggerize-hapi that makes working with Swagger a smart pick. We adapted their way of generating the application’s routing based on the Swagger document.

Having this description, we can take API design a bit further, by generating the whole routing system in our application. This way we only have to care about our business logic and don’t bother with the routing or even validation.

With Swagger, no more:

  • inconsistent API description
  • arguments between developers (at least not on this)
  • springily breaking applications
  • documentation writing, but I am sure no one is going to miss that

If you read our blog you are familiar with the fact that we’re using Hapi for most of our node services.

What we have to do is essentially a Hapi plugin, and plug it into our server. With JOI validation available, we not only get the plain routes, but the types are casted to the types defined in the description, and the payload is already validated. That’s what I call Swagger.

But enough of the theory, lets see some examples!

The Swagger Descriptor

This methodology is called design-driven development. Firstly we design our endpoints’ behavior by describing them in either a YML or a JSON file. This is the most important task and everyone in the team should take part of it.

I prefer YML over JSON, but that’s really just personal preference.

This is a boilerplate Swagger document, it has a pretty readable look:

swagger: '2.0'
info:
  title: SAMPLE API
  version: '0.0.1'
host: 0.0.0.0
schemes:
  - http
  - https
basePath: '/v1'
produces:
  - application/json

To specify paths, we have to add additional properties to our YML document.

paths:
  /info:
    get:
      tags:
      - info
      summary: returns basic info of the server
      responses:
        200:
          description: successful operation
        default:
            description: unexpected error
            schema:
            $ref: Error

What this snippet does is it creates an /info endpoint, that returns 200 OK if everything went well and an error if something bad happened.

But wait, what is $ref? That is Swagger’s way to stay DRY. You can define the API resources in your Swagger file. Write once, use anywhere.

Using Swagger with Node.js

Let’s create a User resource, users commonly require a username and password.
Upon POST-ing this resource to the server it will be validated against this very schema. That’s something that enjoi does magically for you: no more validation is needed in your route handler (in the background it just creates joi schemas from JSON schemas).

definitions:
  User:
    type: object
    required:
    - username
    - password
    properties:
      id:
        type: string
      username:
        type: string
      password:
          type: string

When creating a server, just create a Hapi plugin for your API.

var Hapi = require('hapi'),
var swaggerize = require('swaggerize-hapi');

var server = new Hapi.Server();

server.register({
    plugin: swaggerize,
    options: {
        api: require('./config/pets.json'),
        handlers: Path.join(__dirname, './handlers')
    }
});

Swagger for Microservices

Initially, we talked about using Swagger for defining the communication between client and server – but it can work between servers as well.

If you have multiple HTTP-based microservices it is quite easy to get lost with all their interface, but not with Swagger. You can simply build an API catalog with all your services and their exposed functionality, make it searchable, and you will never implement anything twice.

The Swagger UI

The builder automatically creates the /api-docs endpoint where the JSON description is available.

Using that, Swagger has an online viewer where users can try your API in just a couple of clicks. Here anyone can view your API definition, try those POSTPUTs and DELETEs on the page live. Definitely check this out, it spares you the time to build docs page: Swagger-UI.

Swagger UI for Node.js

They even have a Docker image available. Plug and play with just a couple of commands you can run your own Swagger-ui.

docker build -t swagger-ui-builder .
docker run -p 127.0.0.1:8080:8080 swagger-ui-builder

Huge thanks to the guys working on this. Keep up the awesome work!

Further Readings

Share this post

Twitter
Facebook
LinkedIn
Reddit