Documenting Go REST services with S̶w̶a̶g̶g̶e̶r̶ Open API

Imagine yourself in a situation, where you have built a REST service with Go and now you want to document it for others or for your future self. You want to stick with the trends and choose one of the most popular specs — S̶w̶a̶g̶g̶e̶r̶ Open API.

So, you go on a search to find the tools that are capable of generating documentation from your Go code, because writing documentation by hand takes too much time and you rather spend it doing other, more interesting stuff…

Lastly, you find two popular tools go-swagger and swaggo, that are capable to do what you want and you choose one. Then add necessary comments, add necessary dependencies and hit that magical 🅶🅴🅽🅴🆁🅰🆃🅴 button! Okay, okay, write magical words in a command line and hit enter… The tool does the job and the documentation is accessible. Happiness hits you and you start to feel that the life once again has some meaning…

… until you notice that documentation is in Swagger (also known as v2) and all the world around you are using newer format — Open API (also known as v3). As the tools does not support new format this leads you to a dead end? Or maybe there is still some hope left?

Of course there is, there are plenty of other tools to help if you are willing to add some additional dependencies in your environment. There is an official tool for converting old format to new one, FREELY offered by Swagger.io.

For simplicity, I’ll reference older, Swagger, format as v2 and newer one, Open API, as v3 for the remaining part of the article.

With the site mentioned previously we can convert the v2 into the v3, update our Go source files and live almost happily ever after. Almost…

Well if our service is a final product and it will never change, then this one time action will be sufficient for our use case.

But what to do, when REST service is updated and new things are added or old ones are removed? Should we manually call this service every time? Is this the best approach?

IMHO, the answer to these questions is to AUTOMATE IT!

And to do this, we will have to follow these steps:

  1. Generate documentation
  2. Send generated documentation to the converter
  3. Replace existing documentation with generated one
  4. Build our program with new sources

And the most awesome thing that all the tools already exists to help us on our short journey. So let’s get started

Generating

This is the initial, easy step, where we will have to generate the documentation. For this, our service will need to have required comments in the code and they do differ depending on which library we are using, so check out official repositories and add necessary comments in the code.

Swaggo

When using swaggo and our main.go file is in the root directory of the package, then we will simply need to run following command:

swag init

However, if we are using something more advanced, where our main.go file is placed in the cmd/<service-name> directory, then we will have to run following command:

swag init -g cmd/<package-name>/main.go

If neither one of these command are working, you can check official repository issues page, especially #428 for more insights.

If the everything went smoothly, then there should be following files generated in our package directory:

├── docs
│ ├── docs.go
│ ├── swagger.json
│ └── swagger.yaml

By default, the v2 content is served from docs.go and not from those two additional files. This causes us some issues, but lets leave this for later.

Go-swagger

When using go-swagger we will need to run following command:

swagger generate spec -o ./docs/swagger.json

This will generate swagger.json file in the docs directory of our package.

Converting

Second step is to convert that v2 file into v3. Now there are couple ways to do this, first is to use publicly available service at https://converter.swagger.io/ by calling:

curl -X POST https://converter.swagger.io/convert -d @docs/swagger.json --header 'Content-Type: application/json' > openapi.json

This will save v3 content into openapi.json file.

Another way is to use docker and convert this locally. In order to do this, we will will have to install docker itself and run swagger converter locally. Then above curl command can be used by changing from the public URL to the local one.

If the documentation is served from some external sources, then the journey ends here. We just need to place the openapi.json file to the location from where it would be reachable.

Replacing

However if this documentation is served from the service itself and our service is using default approach (swaggo), then there is a slight of a problem. We will have to replace v2 into v3 in the docs.go file.

To save all the trouble, here is a magical command that does that:

sed -i '/var doc = `{/,/}`/c\var doc = `'"$(cat openapi.json)"'`' docs/docs.go

This will replace doc variable value with the content from openapi.json file.

Building

Now, the last thing that is left is to run go build to regenerate the binaries and we will be able to access v3 documentation from our service, when it is running (again swaggo).

By the way if you want to use similar approach in your CI /CD flow, you can check this GitHub repository to see how this works inside GitHub Actions.

Side Notes

#1

Swaggo have builtin swagger page, however it does not support v3 documentation quite well, so it would be best to run swagger UI or swagger editor separately and serve your service documentation from it.

#2

I wanted to include examples with go-sawgger as well in GitHub, but after spending several hours, while stepping on various errors, finding myself looking on issues that are opened for more than 2 years and being forced to change my structures just to see that instead of an error, you are getting incomplete and inaccurately generated documentation, I decided to ditch this idea and go with swaggo instead. Another thing that is worth to mention is that, IHMO, go-swagger is more verbose than swaggo.

License notes

Gopher image was created by Takuya Ueda, source https://github.com/golang-samples/gopher-vector

Swagger logo: https://static1.smartbear.co/swagger/media/assets/images/swagger_logo.svg

Open Api logo source: https://www.openapis.org/wp-content/uploads/sites/3/2018/02/OpenAPI_Logo_Pantone-1.png

Links


Go, Swagger, and Open API was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.