Swagger UI setup for Go REST API using Swaggo (2024)


golangswaggerrestapi

In a previous post - Go REST API, we saw how to build a simpleREST service in Golang. This post is intended as a follow-up, and explains how to generate swagger documentation andsetup Swagger UI for our APIs using Swaggo.

Why Swagger?

Once we have our super-cool API ready, the next step is to share it with consumers and make it easy for them tounderstand and use the API. Building an API is only half the job 😄 The other half is enablingclients to use, explore and test the API without too much hassle. Without a clear documentation of APIs, consumers are going tofind it hard to do all of the above, which leads to a serious loss in developer productivity.

Once setup, Swagger UI provides a convenient way for consumers to explore the API and play around with it.Also, APIs evolve over time and the documentation should reflect the changes accordingly (The number of bugs thatarise due to improper(or non-existent) communication of changes to APIs is just too damn high!). With Swagger, updating/maintaining API documentation is a breeze - the developer just has to add/tweak annotations in the code, and the changes are incorporated when the API doc is generated next.

Wait - What are my options?

Swaggo and go-swagger are two of the mostpopular frameworks available for generating Swagger docs and UI (Looking at the number of stars on Github, go-swagger appears to be more popular). However, I found Swaggo to be simple and hassle-free and can be a goodstarting point for documenting APIs in Go. I will write another post on doing the same with go-swagger and tryto provide some comparisons between both.

In our previous post on Go APIs, we used Go’s built-in net/http library in combination with Gorilla Mux for routing. We will retain the same for this post, and build upon it byadding swagger-specific libraries and annotations.

Swaggo setup

Our first task is to install the libraries we are dependent on. Run the following commands from the commandline:

go get -u github.com/swaggo/swag/cmd/swaggo get -u github.com/swaggo/http-swaggergo get -u github.com/alecthomas/template

The first two commands install swag and http-swagger respectively:

swag - This library converts Go annotations to Swagger 2.0 docs (swagger.json/swagger.yaml), which is later used byhttp-swagger to serve the Swagger UI.

http-swagger - This library helps to serve the Swagger UI using the docs generated by swag

The third command is to install template, a fork of Go’s text/template package. This dependency is required in the docs.go file generated by swag, and we’ll see an error whilerunning the application without it.

Generate Swagger documentation

Let us divide this whole process of API documentation into 3 steps:

  1. Adding annotations in code
  2. Generating Swagger specs (swagger.json and swagger.yaml)
  3. Serving the Swagger UI using the specs generated in the previous step

1. Adding annotations in code

General API info

We start by adding a general description for the entire project by annotating our main method. These annotations are nothing but comments beforethe method definition, as you can see below.

// @title Orders API// @version 1.0// @description This is a sample serice for managing orders// @termsOfService http://swagger.io/terms/// @contact.name API Support// @contact.email soberkoder@swagger.io// @license.name Apache 2.0// @license.url http://www.apache.org/licenses/LICENSE-2.0.html// @host localhost:8080// @BasePath /func main() {router := mux.NewRouter()... log.Fatal(http.ListenAndServe(":8080", router))}

I feel these annotations are self-explanatory. For more information, the exhaustive list of all possible annotations isavailable on the swag github page.The annotation we need to pay attention to are the @host and @BasePath - Once the swagger UI is app and we tryout sample API calls from the UI, this path will be used for API invocation.

API Operation annotations

Now that we have added project-level documentation, let’s add documentation to each individual API. For reference, Iam only showing this for the getOrders API below.

// GetOrders godoc// @Summary Get details of all orders// @Description Get details of all orders// @Tags orders// @Accept json// @Produce json// @Success 200 {array} Order// @Router /orders [get]func getOrders(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(orders)}

Again, a lot of these annotations are self-explanatory. The @Success annotation specifies how a successful responsefrom the API looks like - 200 is the response code, {array} specifies that the response is an array oftype Order.

This is a simple GET API, and doesn’t have any request body. The below is a POST method that has arequest body.

// CreateOrder godoc// @Summary Create a new order// @Description Create a new order with the input paylod// @Tags orders// @Accept json// @Produce json// @Param order body Order true "Create order"// @Success 200 {object} Order// @Router /orders [post]func createOrder(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json")var order Orderjson.NewDecoder(r.Body).Decode(&order)prevOrderID++order.OrderID = strconv.Itoa(prevOrderID)orders = append(orders, order)json.NewEncoder(w).Encode(order)}

The request body is described by the @Param annotation, which has the following syntax:

 @Param [param_name] [param_type] [data_type] [required/mandatory] [description]

The param_type can be one of the following values:

  1. query (indicates a query param)
  2. path (indicates a path param)
  3. header (indicates a header param)
  4. body
  5. formData

Example values for model attributes

In addition to documenting the request/response for each API, we can also provide example values forfields in the request. The API developer could provide valid/sensible samples for fields, so that clients cantry out API from swagger UI, these sample values are used for the request payload. For example, we have providedexample values using the example tag for the Order and Item model.

// Order represents the model for an ordertype Order struct {OrderID string `json:"orderId" example:"1"`CustomerName string `json:"customerName" example:"Leo Messi"`OrderedAt time.Time `json:"orderedAt" example:"2019-11-09T21:21:46+00:00"`Items []Item `json:"items"`}// Item represents the model for an item in the ordertype Item struct {ItemID string `json:"itemId" example:"A1B2C3"`Description string `json:"description" example:"A random description"`Quantity int `json:"quantity" example:"1"`}

The request payload generated by Swagger for the CreateOrder API looks something like the following:

{ "customerName": "Leo Messi", "items": [ { "description": "A random description", "itemId": "A1B2C3", "quantity": 1 } ], "orderId": "1", "orderedAt": "2019-11-09T21:21:46+00:00"}

2. Generate swagger.json

Once we are done annotating our main method and all the APIs, we shall generate the swagger docs with the swaginit command, as below:

# In your project dir (~/GOPATH/src/swaggo-orders-api normally)swag init -g orders.go

By default, the init command looks for the general API annotations in the file named main.go. If we have namedour files differently, we can pass the file path(which in our case is orders.go) with the -g option.
We should see a similar output, and you can navigate to the docs directory and view the swagger.json file, if youare curious.

019/12/02 19:19:43 Generate swagger docs....2019/12/02 19:19:43 Generate general API Info, search dir:./2019/12/02 19:19:43 create docs.go at docs/docs.go2019/12/02 19:19:43 create swagger.json at docs/swagger.json2019/12/02 19:19:43 create swagger.yaml at docs/swagger.yaml

3. Swagger UI

This step is pretty straightforward (very much like the previous steps 😄). All we are doing here is importingthehttpSwagger library, and the swagger docs we generated in Step 2. If you are wondering about the _ in the imports, it’s justa way of importing packages for side-effects. (Wait, that’snot very clear either!) It means that our code is not explicitly calling any methods from the package, but it’spossible that the package may perform actions like registering handlers, for example.

import ("encoding/json""log""net/http""strconv""time"_ "swaggo-orders-api/docs" // docs is generated by Swag CLI, you have to import it.httpSwagger "github.com/swaggo/http-swagger""github.com/gorilla/mux")

In addition to specifying the routes for all our APIs, we’ll have to define a route in our main method for serving theSwagger UI using the PathPrefix method.

// @title Orders API// @version 1.0// @description This is a sample service for managing orders// @termsOfService http://swagger.io/terms/// @contact.name API Support// @contact.email soberkoder@gmail.com// @license.name Apache 2.0// @license.url http://www.apache.org/licenses/LICENSE-2.0.html// @host localhost:8080// @BasePath /func main() {router := mux.NewRouter()// Createrouter.HandleFunc("/orders", createOrder).Methods("POST")// Readrouter.HandleFunc("/orders/{orderId}", getOrder).Methods("GET")// Read-allrouter.HandleFunc("/orders", getOrders).Methods("GET")// Updaterouter.HandleFunc("/orders/{orderId}", updateOrder).Methods("PUT")// Deleterouter.HandleFunc("/orders/{orderId}", deleteOrder).Methods("DELETE")// Swaggerrouter.PathPrefix("/swagger").Handler(httpSwagger.WrapHandler)log.Fatal(http.ListenAndServe(":8080", router))}

The above code snippet shows our main method after adding the Swag annotations, and a route for swagger UI.

Finally, once we are done with all the APIs, and it’s time take them for a spin.To run the app, navigate to your project directory, and run the following commands:

go run orders.go

You can see your work coming to life by loading the swagger UI at http://localhost:8080/swagger/index.html

If everything goes well, we should be seeing a UI like below:

Swagger UI setup for Go REST API using Swaggo (1)

You can also view the swagger json at the following location:

http://localhost:8080/swagger/doc.json

Swagger also provides an option to visualize the swagger docs using the Swagger editor online. You can just copy the contents of doc.json or doc.yaml and pasting it on the editor on the lefthalf of the page shows the swagger UI on the right half.

Swagger UI setup for Go REST API using Swaggo (2)

In addition to viewing the API documentation, we can see an API in action by trying it out directly from the SwaggerUI. There should be a Try it out button at the top right corner for each API, clicking this should display arequest with values generated based on the example values we provided earlier (We can edit it if required). Clickingon the execute button invokes the API and displays the response details (payload + headers).

Swagger UI setup for Go REST API using Swaggo (3)

Setting up a makefile

Now, what happens when we update our APIs (Add a new one, modify the request/response of existing ones, etc)? Doesthe documentation get updated automatically? Unfortunately, no 😞 We’ll have to run the swag init command to regenerate the docs to reflect the updated API. Since this is something we’ll find ourselves doingoften, wouldn’t it be nice if this is automated?To automate this, we can setup a makefile and configurethe swag init command to be executed everytime we run the application. In the below snippet, we create a maketarget named run, which generates the swagger docs before running the application.

run: swag init -g orders.go go run orders.go

When the run target is executed:

swaggo-orders-api$ make runswag init -g orders.go2020/06/20 08:12:24 Generate swagger docs....2020/06/20 08:12:24 Generate general API Info, search dir:./2020/06/20 08:12:24 Generating main.Order2020/06/20 08:12:24 Generating main.Item2020/06/20 08:12:24 create docs.go at docs/docs.go2020/06/20 08:12:24 create swagger.json at docs/swagger.json2020/06/20 08:12:24 create swagger.yaml at docs/swagger.yamlgo run orders.go

Conclusion

I hope you now know how to setup Swagger UI for Go APIs, and hope you do this for your APIs going forward.I again want to emphasize the importance of having a clean and updated documentation (If there is one thing you wannatake away from this post, let this be it 😄) )You can find the entire code on Github - Please feel free to reach out if there are any questions or suggestionsand I’d love to hear your thoughts in the comments, as always.

See Also

  • Build a REST API in Golang with MySQL, GORM and Gorilla Mux
  • Consuming REST APIs in Go - HTTP GET, PUT, POST and DELETE
  • Build a REST API in Golang
Swagger UI setup for Go REST API using Swaggo (2024)
Top Articles
Latest Posts
Article information

Author: Horacio Brakus JD

Last Updated:

Views: 6156

Rating: 4 / 5 (71 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Horacio Brakus JD

Birthday: 1999-08-21

Address: Apt. 524 43384 Minnie Prairie, South Edda, MA 62804

Phone: +5931039998219

Job: Sales Strategist

Hobby: Sculling, Kitesurfing, Orienteering, Painting, Computer programming, Creative writing, Scuba diving

Introduction: My name is Horacio Brakus JD, I am a lively, splendid, jolly, vivacious, vast, cheerful, agreeable person who loves writing and wants to share my knowledge and understanding with you.