Tuesday, December 24, 2019

Swagger UI for ExpressJS

Swagger is a tool that allows to describe a service API. One of the reasons for that is creation of documentation for all API functions so make it easy to examine and navigate through. Even further, swagger allows to call the API functions in a simple manner like let's say Postman does. So working with ExpressJS I just discovered the swagger-ui-express library that gives us opportunity to build the swagger UI in literaly few steps. So I created the simplest possible example (Github Link) that will be be taken to pieces below step-by-step.

As usually, we start with installing the package npm install -s swagger-ui-express.

Now let's create a simple ExpressJS HTTP server with several CRUD functions.

const express = require('express');
const app = express();

const uuidv4 = require('uuid/v4');

//stores the books collection
let _books = [];

app.route('/api/book')
    .get(function (req, res) {
        res.json(_books.filter(b => b.id == req.query.id));
    })
    .put(function (req, res) {
        let book = JSON.parse(JSON.stringify(req.query));
        book.id = uuidv4();
        _books.push(book);
        res.json(book);
    })
    .delete(function (req, res) {
        _books = _books.filter(b => b.id != req.query.id);
        res.json(_books);
    })

app.get('/api/books', function (req, res) {
    res.json(_books);
});


// start the server in the port 3000
app.listen(3000, function () {
    console.log('Start app listening on port 3000.');
});

The service exposes functions allow to get/add/delete records (books) and retrieve all the books as well.

Next step is to display that API on UI.

The UI is described in the only file swagger.json:

{
    "swagger": "2.0",
    "info": {
        "title": "Swagger Test ExpressJS API",
        "version": "version 1.0"
    },
    "schemes": [
        "http",
        "https"
    ],
    "consumes": [
        "application/json"
    ],
    "produces": [
        "application/json"
    ],
    "paths": {
        "/api/books": {
            "get": {
                "summary": "GET /api/books",
                "responses": {
                    "200": {
                        "description": ""
                    }
                },
                "tags": [
                    "Generic"
                ]
            }
        },
        "/api/book": {
            "put": {
                "summary": "PUT /api/:book",
                "responses": {
                    "200": {
                        "description": ""
                    }
                },
                "tags": [
                    "Generic"
                ],
                "parameters": [
                    {
                        "in": "query",
                        "name": "title",
                        "required": true,
                        "type": "string"
                    },
                    {
                        "in": "query",
                        "name": "author",
                        "required": true,
                        "type": "string"
                    },
                    {
                        "in": "query",
                        "name": "year",
                        "required": true,
                        "type": "number"
                    }
                ]
            },
            "get": {
                "summary": "GET /api/:book",
                "responses": {
                    "200": {
                        "description": ""
                    }
                },
                "tags": [
                    "Generic"
                ],
                "parameters": [
                    {
                        "in": "query",
                        "name": "id",
                        "required": true,
                        "type": "string"
                    }
                ]
            },
            "delete": {
                "summary": "DELETE /api/:book",
                "responses": {
                    "200": {
                        "description": ""
                    }
                },
                "tags": [
                    "Generic"
                ],
                "parameters": [
                    {
                        "in": "query",
                        "name": "id",
                        "required": true,
                        "type": "string"
                    }
                ]
            }
        }
    }
}

swagger.json file can contain much more options, but the example above uses just few of them necessary for the service. Ref Swagger Documentation if you are interested in more details.

And the final step is to add a route for the swagger UI. That could be done after const app = express(); line.

const swaggerJson = require('./swagger.json');
const swaggerUi = require('swagger-ui-express');
app.use('/swagger', swaggerUi.serve, swaggerUi.setup(swaggerJson));

So now after running the Express http server locally, the swagger UI is accessible via http://localhost:3000/swagger. As expected, there are 4 API functions on the page:

They are expandable, so clicking on them brings a frame with all necessary options/messages like request details, response body, response headers, query parameters. For example, click PUT /api/book, then Try it out, then fill in all necessary parameters (title, author, year), then press the Execute button.

As the result we can see just created record:

{
  "title": "The Lord of the Rings",
  "author": "Tolkien",
  "year": "1952",
  "id": "882fce04-0607-4868-beae-0393e96ab388"
}

Let's add some more records, then use the GET /api/books function, we get the list of all the books we added:

Another great option here is the Download button that allows to save the response as the json file.

Happy Swaggering!

No comments:

Post a Comment