Documenting & hosting Swagger application APIs

A step by step guide to documenting & hosting your application APIs with Swagger.

While it is possible to do so using Swagger on-line editor and SwaggerHub this guide shows how to create you openAPI documentation locally and host it as part of your application.

1. About Swagger

Swagger or openAPI is the a set of the design and documentation tools for creating the openAPI Specification for your application.

For more information about Swagger visit: https://swagger.io/ website.

2. Set up
2.1. Prerequisites

This tutorial assumes that you are using Atom IDE and have Node js isntalled globally.

2.2. Creating GitHub repository

Create a new GitHub repo and copy its address. Then go to your projects directory at command prompt and clone your new repo. This creates your new project directory locally, eg.

git clone https://github.com/CriptoGirl/myFullStackAppDocs.git

Create .gitignore file in the project directory as following:

*node_modules/

2.3. Seting up a local Server Project
Create a Project Directory

Create a project folder, e.g. myProjectDocs in your Projects directory.

Initilise node.js environment

Go to this directory and create a new node.js package by running the following command at the command prompt:

npm init

Install Express and swagger libraries

Express is a lightweight web application framework for Node.js, which provides a robust set of features for writing web apps. These features include route handling, template engine integration and a middleware framework. Type following command at the command line:

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

--save option, adds the library to the dependencies section of the package.json file.

Creating the Node js Application to serve swagger documentation

In your application folder create index.js file, then add the following code to it:

const app = require('./startup/app');

const server = app.listen(process.env.PORT || 5000, () => {
  console.log(`Express is running on port ${server.address().port}`);
});

Create startup folder under the server folder and add app.js file to it containing the following code:

// libraries
const express = require('express');
const app = express();
const swaggerJSDoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');
// options for the swagger doc
const swaggerDefinition = {
  openapi: '3.0.0',
  info: {
    version: '1.0.0', // Version of the app
    license: { name: 'MIT', url: 'https://spdx.org/licenses/MIT.html' }
  },
  servers: [
    {url: 'http://localhost:5002/', description: 'Localhost'},
    {url: 'https://sampleservices.com:5002/', description: 'Staging server for testing'}
  ],
  components: {
    securitySchemes: {
      bearerAuth: {
        type: 'http',
        scheme: 'bearer',
        bearerFormat: 'JWT'
      }
    }
  },
  security: { bearerAuth: [] }
}
// customize for System Data API
swaggerDefinition.info.title = 'Sample System Data API'
let options = { swaggerDefinition, apis: ['./swaggerDocs/systemData.yaml'] }
// generate swagger document
const swaggerDocument = swaggerJSDoc(options);
// routes: use swagger-Ui-express for your app documentation endpoint
app.use('/', swaggerUi.serve, swaggerUi.setup(swaggerDocument));  //

module.exports = app;

Start the Server & test

At command prompt, go to the server folder and type the following command to start the Server:

nodemon

This should start the Server.

Test navigation in a browser.

Commit to GitHub

At command prompt go to the project directory and execute following commands to commit your local code to GitHub:

git add .
git commit -m "server code"
git push

2.4. Add Swagger Linter to Atom
Add Swagger Linter to your Atom IDE

Open up the Atom Preferences, and navigate to the Install tab. This is where you install Atom Packages.

In the Install tab, enter swagger in the search box. The results will include a package named linter-swagger and another for linter-swagger-improved.

Install linter-swagger and install linter as well.

Once you've done that, you can edit an OpenAPI specification directly in Atom. It will interactively warn of problems with the code. That's great, and it's just as useful as in the Swagger Editor. But, it doesn't have that nice browsing of the API like you get in the Swagger Editor. The advantage is that you're in a real programmers editor, with direct access to files on your filesystem.

For more information see: https://techsparx.com/software-development/openapi/edit-swagger-api-documents.html website where I have got the above instructions.

2.5. Create YAML file

Create swaggerDocs directory under your project folder.

Than, create sample.yaml file in the above directory, containing:

paths:
  /countries/:                # path of the user from your endpoint
    get:
      tags: ['System Data: countries']
      summary: Returns a list of all countries.
      security:
        - bearerAuth: []
      responses:
        200:  # status code
          description: A list of Countries
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Country"
        403:
          description: Not authorised.
        500:
          description: An unexpected error occured.
          tries:

    post:
      tags: ['System Data: countries']
      summary: Creates a country.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - code
                - name
              properties:
                code:
                  type: string
                  description: 2 char country code.
                name:
                  type: string
                  description: Country name.
                status:
                  type: string
                  enum: ["Current", "Not in use"]
                  description: Country status code.
            example:
              code: "GB"
              name: "United Kingdom"
              status: "Current"
      responses:
        201:
          description: "Country added. Code: {{countrycode}}."
        403:
          description: Not authorised.
        422:
          description: Unprocessable Entity.
        500:
          description: An unexpected error occured.

    put:
      tags: ['System Data: countries']
      summary: Update country.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - code
                - name
              properties:
                code:
                  type: string
                  description: 2 char country code.
                name:
                  type: string
                  description: Country name.
                status:
                  type: string
                  enum: ["Current", "Not in use"]
                  description: Country status code.
            example:
              code: "GB"
              name: "United Kingdom"
              status: "Current"
      responses:
        201:
          description: "Country updated."
        403:
          description: Not authorised.
        404:
          description: Country not found.
        422:
          description: Unprocessable Entity.
        500:
          description: An unexpected error occured. Country could not be updated.

  /countries/{code}:
    delete:
      tags: ['System Data: countries']
      summary: Delete country.
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: code
          schema:
            type: string
          required: true
          description: Code of the country that needs to be deleted
          example: 'XX'
      responses:
        201:
          description: "Country deleted."
        403:
          description: Not authorised.
        404:
          description: Country not found.
        422:
          description: Unprocessable Entity.
        500:
          description: An unexpected error occured. Country could not be updated.

components:
  schemas:
    Country:
      type: object
      required:
        - code
        - name
        - status
        - createdAt
        - updatedAt
      properties:
        code:
          type: string
          description: 2 char country code.
          example: GB
        name:
          type: string
          description: Country name.
          example: United Kingdom
        status:
          type: string
          enum: ["Current", "Not in use"]
          description: Country status code.
          example: Current
        createdAt:
          type: string
          format: date-time
          description: Record created at date-time.
          example: "2020-10-15T17:05:03.000Z"
        updatedAt:
          type: string
          format: date-time
          description: Record updated at date-time.
          example: "2020-10-15T17:05:03.000Z"

Test in a browser.

3. Swagger API Static Pages
3.1. Create static directory structure

Add static_docs directory under the server directory of your project.

Create a directory for each API Documentation File, e.g. system_data directory under the static_docs directory.

3.2. Generating Static Swagger Pages
Download Swagger Page & Supporting files

In your local environment start your Documenation Server.

In a browser right-click on the documentation page and choose Save as... option. Make sure that you save as type: Web Page, Complete option. You can save directly to the static_docs folder in your project.

Rename Swagger UI.html as index.html.

3.3. Serving Static Swagger Pages

Add following to your project's app.js file:

// serving static swagger pages
app.use('/api_docs_system_data', express.static('static_docs/system_data'));

Add call to the new route from your application front end.

Test

Test using your application.

Publish new API Specification

Repeat steps 2.5, 3.1, 3.2 and 3.3 for any new API doc.

4. Other Info

Other usefull packages:

npm install @alt3/sequelize-to-json-schemas --save

npm install --save yamljs