What is a swagger?

Swagger is a simple but powerful API expression tool. It has the largest ECOSYSTEM of API tools on earth, with thousands of developers, using almost every modern programming language, all supporting and using Swagger. With Swagger generating apis, we get interactive documentation, SDKS that automatically generate code, and DISCOVERY features for apis.

What does a Swagger document look like?

A simple Example of a Swagger document:

swagger: "2.0"

info:
  version: 1.0. 0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths: {}
Copy the code

Assuming you already know how to write a Swagger document, of course, if you don’t, check out the documentation on the swagger website to learn how to do it, and there’s a set of Swagger From Getting Started to Mastering.

Background of this paper

The reason for writing this article is because the company requires the API documentation to be in Swagger format and the project is written in Golang. How can a lazy programmer bear to write such complicated Swagger documentation? Is there a one-click generation tool? Google it, and it’s called the Go-Swagger project. One of the many features of The Go-Swagger is Generate a spec from source, which suits my needs.

How to add Swagger comments to a project and generate API documentation with one click

Two tools need to be installed before you can begin:

  • Swagger-editor: For Writing Swagger documentation, UI presentation, generating code, etc…
  • Go-swagger: For one-click GENERATION of API documentation

Install swagger – editor, here I use the docker run, other installation, please see the official document:

docker pull swaggerapi/swagger-editor
docker run --rm -p 80:8080 swaggerapi/swagger-editor
Copy the code

Install the Go-Swagger, I use BREW installation, other installation, please see the official documentation

brew tap go-swagger/go-swagger
brew install go-swagger
Copy the code

Ok, now we finally get down to business: Start coding!!

Start writing comments

1. Suppose you have a user.server that provides some REST API for adding, deleting, modifying and querying user data.

For example, here is a getOneUser interface that queries user information:

package service

import (
    "encoding/json"
    "fmt"
    "net/http"
    "strconv"
    "user.server/models"
    "github.com/Sirupsen/logrus"
)

type GetUserParam struct {
    Id int `json:"id"`
}

func GetOneUser(w http.ResponseWriter, r *http.Request) {
    defer r.Body.Close()
    decoder := json.NewDecoder(r.Body)
    var param GetUserParam
    err := decoder.Decode(&param)
    iferr ! =nil {
        WriteResponse(w, ErrorResponseCode, "request param is invalid, please check!".nil)
        return
    }

    // get user from db
    user, err := models.GetOne(strconv.Itoa(param.Id))
    iferr ! =nil {
        logrus.Warn(err)
        WriteResponse(w, ErrorResponseCode, "failed".nil)
        return
    }
    WriteResponse(w, SuccessResponseCode, "success", user)
}
Copy the code

According to the Swagger Documentation specification, a Swagger document starts with the swagger version and info. To use the go-Swagger, just declare the package with the following comment:

// Package classification User API. // // The purpose of this service is to provide an application // that is using Plain Go code to define an API // // Host: localhost // Version: 0.0.1 // // Swagger: Meta Package serviceCopy the code

/swagger.json: Swagger generate spec -o./swagger.json

This command finds the main.go entry file, then iterates through all the source files, parses and generates a swagger.json file

{
  "swagger": "2.0"."info": {
    "description": "The purpose of this service is to provide an application\nthat is using plain go code to define an API"."title": "User API."."version": "0.0.1"
  },
  "host": "localhost"."paths": {}}Copy the code

2. The basic information is there, then there is the route, the request, the response, etc.

// swagger:parameters getSingleUser
type GetUserParam struct {
    // an id of user info
    //
    // Required: true
    // in: path
    Id int `json:"id"`
}

func GetOneUser(w http.ResponseWriter, r *http.Request) {
    // swagger:route GET /users/{id} users getSingleUser
    //
    // get a user by userID
    //
    // This will show a user info
    //
    // Responses:
    // 200: UserResponse
    decoder := json.NewDecoder(r.Body)
    var param GetUserParam
    err := decoder.Decode(&param)
    iferr ! =nil {
        WriteResponse(w, ErrorResponseCode, "request param is invalid, please check!".nil)
        return
    }

    // get user from db
    user, err := models.GetOne(strconv.Itoa(param.Id))
    iferr ! =nil {
        logrus.Warn(err)
        WriteResponse(w, ErrorResponseCode, "failed".nil)
        return
    }
    WriteResponse(w, SuccessResponseCode, "success", user)
}
Copy the code

You can see that the GetUserParam structure has added a swagger: Parameters getSingleUser comment above it. This is the input comment for declaring the interface. Several lines of comments inside the structure indicate that the id parameter is required and that the query parameter ID is in the URL path. Swagger :params

In the GetOneUser function:

  • swagger:routeSpecifies the HTTP method and route to be used, as well as the tag and operation ID. For details, see swagger:route
  • ResponsesSpecifies the code and type of the return value

Then declare the response:

// User Info
//
// swagger:response UserResponse
type UserWapper struct {
    // in: body
    Body ResponseMessage
}

type ResponseMessage struct {
    Code    int         `json:"code"`
    Message string      `json:"message"`
    Data    interface{} `json:"data"`
}
Copy the code

Use swagger:response syntax to declare the return value, and the next two lines are a description of the return value. For details on usage, see; swagger:response

Then go to LocalHost in your browser and view the Swagger-Editor interface. Click File->Impoprt File in the toolbar to upload the swagger.json File you just generated.

A simple API documentation is generated

3. How’s it going? Is it simple? But it feels like it’s not right. Well, the comments are in the code, it’s ugly, and it’s not easy to maintain. Think go-Swagger works by scanning all the GO files in the directory and parsing the comment information. So is it possible to write API comments in a single file, unified management, lest scattered in various source files.

Create a new doc.go file, and there is another interface called UpdateUser, so we declare the API comments for this interface in the doc.go file. Let’s look at the UpdateUser interface code:

func UpdateUser(w http.ResponseWriter, r *http.Request) {
    defer r.Body.Close()
    // decode body data into user struct
    decoder := json.NewDecoder(r.Body)
    user := models.User{}
    err := decoder.Decode(&user)
    iferr ! =nil {
        WriteResponse(w, ErrorResponseCode, "user data is invalid, please check!".nil)
        return
    }

    // check if user exists
    data, err := models.GetUserById(user.Id)
    iferr ! =nil {
        logrus.Warn(err)
        WriteResponse(w, ErrorResponseCode, "query user failed".nil)
        return
    }
    if data.Id == 0 {
        WriteResponse(w, ErrorResponseCode, "user not exists, no need to update".nil)
        return
    }

    // update
    _, err = models.Update(user)
    iferr ! =nil {
        WriteResponse(w, ErrorResponseCode, "update user data failed, please try again!".nil)
        return
    }
    WriteResponse(w, SuccessResponseCode, "update user data success!".nil)}Copy the code

Then write the following declaration in the doc. Go file:

package service

import "user.server/models"

// swagger:parameters UpdateUserResponseWrapper
type UpdateUserRequest struct {
    // in: body
    Body models.User
}

// Update User Info
//
// swagger:response UpdateUserResponseWrapper
type UpdateUserResponseWrapper struct {
    // in: body
    Body ResponseMessage
}

// swagger:route POST /users users UpdateUserResponseWrapper
//
// Update User
//
// This will update user info
//
// Responses:
// 200: UpdateUserResponseWrapper
Copy the code

Swagger generate spec -o./swagger.json to generate a JSON file, you can see the result:

Write a few lines of comments with reference to the documentation, and then a command generates the API documentation. Good news for lazy programmers

All sample code for this article is hosted here at the original address

Reference:

  • Swagger official Doc
  • Swagger from beginner to master
  • Go to swagger document
  • Go-swagger’s Github home page