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.jsNode.js is an asynchronous event-driven JavaScript runtime and is the most effective when building scalable network applications. Node.js is free of locks, so there's no chance to dead-lock any process. 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 microservicesMicroservices are not a tool, rather a way of thinking when building software applications. Let's begin the explanation with the opposite: if you develop a single, self-contained application and keep improving it as a whole, it's usually called a monolith. Over time, it's more and more difficult to maintain and update it without breaking anything, so the development cycle may... 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 POST
s PUT
s and DELETE
s on the page live. Definitely check this out, it spares you the time to build docs page: Swagger-UI.
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