Create Golang API Documentation with Swagger

When you develop a backend, at some point you always come to the point that you have to explain its interface to other developers. With go-swagger and SwaggerUI we can automatically create an interactive, well-structured API documentation. This blog post shows how to annotate a Golang REST API and create a Swagger specification from it.

A Swagger specification describes the public interfaces of the API and is independent of the programming language.

We will be annotating our Golang API in the code itself.

From that, we will use Go-Swagger to generate a Swagger 2.0 specification file.

This file can be served with SwaggerUI as an interactive documentation of your API.

Installing Go-Swagger

Go to https://github.com/go-swagger/go-swagger/releases and download the latest released version.

Put the executable somewhere you like and add its location to your sytem’s PATH.

I have put it to %GOPATH%/bin/, that is where all other go tools reside.

API Description with swagger:meta

First, we want to provide some metadata for our API, e.g. general description, the version, contact person, security definitions, and so on.

Create a doc.go file on the root level.

Assign it to the main package and add the swagger:meta annotation.

An example can be found below. Besides the mentioned metadata, you will find more in the official swagger:meta documentation.

// Golang Microservice API
//
// Example Swagger spec.
// 
//	Schemes: [http, https]
//	BasePath: /
//	Version: 0.0.1
//	Contact: Matthias Sommer<admin@matthiassommer.it>
//
//	Consumes:
//	- application/json
//
//	Produces:
//	- application/json
//
//      SecurityDefinitions:
//          api_key:
//              type: apiKey
//              name: Authorization
//              in: header
// swagger:meta
package main
  1. Title – Short textual caption
  2. Description – Textual description
  3. Schemes – List of accepted schemes
  4. BasePath – The default base path of the API (prefix to all routes)
  5. Version – current API version
  6. Contact – person to contact (name, email, and url)
  7. Consumes – list of default mime types for the content the API receives
  8. Produces – list of default mime types for the content the API sends
  9. SecurityDefinitions – list of supported authorization types (Oauth, basic or apiKey)

Specifying the accepted schemes and consumption/production mime types on a global level allows us to omit them from the endpoints themselves. Nevertheless, variations in an endpoint can be specified differently, so the global value is overwritten.

When a SecurityDefinition is given, Swagger UI displays an extra button for authorization.

The resulting specification looks like this in Swagger UI:

Swagger UI

Generate the Swagger Specification

Before we move on, let’s generate the Swagger specification file with

%GOPATH%/bin/go-swagger generate spec -o ./swagger.json

You can also create a yml file instead of json. For a full list of command options, go to https://goswagger.io/generate/spec.html.

Serve API Documentation Page

Go-swagger has a command to serve the generated json document:

%GOPATH%/bin/go-swagger serve ./swagger.json

This hosts the specification on your own machine and opens a new tab in your browser with Redoc (http://localhost:57396/docs).

Alternatively, add the -F=swagger parameter to host and open it in Swagger UI instead (http://petstore.swagger.io/).

%GOPATH%/bin/go-swagger serve -F swagger ./swagger.json

Document API Endpoints

Now that we have done the preliminary work, we can start documenting the endpoints of the API. For this, we will use the swagger:operation annotation.

I will explain the details using some concrete examples. I use Echo as my HTTP router, by the way.

Simple endpoint: Health

The first simple example is a health endpoint. It simply returns status code 204 in case the service is running.

// Health returns OK to indicate a running service
func (router *Router) Health(c echo.Context) error {
	return c.NoContent(http.StatusNoContent)
}

This endpoint is annotated as follows:

// swagger:operation GET /health general Health
// Check if the service is running.
// Returns 204 without content
// ---
// responses:
//     '204':
//         description: Service available
router.echo.GET("/health", router.Health)

Here, we have a GET endpoint which can be called at <basepath>/health.

It has a title (second line – sentence must end with a dot) and description (third line). After --- the response type is defined with its status code and a mandatory description.

Complex endpoint: Authentication

The second endpoint expects the user’s username and password and returns an Oauth2 token to the user.

// swagger:operation POST /oauth/token auth GetToken
// Authenticate and authorise with Windows credentials.
// ---
// produces:
// - application/json
// parameters:
// - name: grant_type
//   in: formData
//   description: Grant type
//   required: true
//   type: string
//   default: "password"
// - name: username
//   in: formData
//   description: domain\username
//   type: string
//   required: true
// - name: password
//   in: formData
//   description: Your password
//   required: true
//   type: string
//   format: password
// responses:
//     '200':
//         description: Authenticated
//     '400':
//         description: Bad request
//     '500':
//         description: Internal server error
router.echo.POST("/oauth/token", auth.login)
  1. swagger:operation – Annotation [method] [path] [?tags] [operationId]
  2. POST – HTTP method type
  3. /oauth/token – endpoint path (without base path)
  4. auth – using a tag to group the operation
  5. GetToken – unique operation ID
  6. Next comes a short textual description of the endpoint
  7. The section following --- defines the Swagger spec in yaml notation. Go swagger will not parse it if your intendation is not correct. Use tabs or four spaces (see responses).
  8. parameters – list of input parameters. Each parameter has a name, value type, location type, and an optional description
  9. responses – list of HTTP status codes and a description

I would like to emphasise a few more points.

You can use the default keyword to prefill the Swagger UI input with a default value (e.g. default: "password"). If you want to set a fixed value which cannot be changed in the UI, use the following:

// - name: grant_type
//   in: formData
//   description: Grant type
//   required: true
//   type: string
//   enum: ["password"]

By default, all parameters are optional. A mandatory field can be set with required: true.

API Documentation with Swagger

Summary

This concludes the first part of this series.

In this blogpost we have seen how to create API documentation using go-swagger and Swagger UI for a Golang API.

Resources