June 10, 2018

Serve SwaggerUI within your Golang application

I’ve previously written an Article on generating OpenAPI (Swagger) spec automatically within Golang. It’s the most popular article on this blog since lots of developers are searching for it. In it, I mentioned that in order to serve the swagger.json with SwaggerUI, a Docker instance is required that will serve SwaggerUI. There is an easier way to implement it, and this article will demonstrate how to do it with net/http, Gin and Echo.

Comming from SpringBoot, I was used to having a SwaggerUI served automatically once the dependency for it was added. With few annotations, visiting /swagger-ui would provide a SwaggerUI with all endpoints listed.

However, in Go, not everything is as easy as that. Generating Swagger.json is bit troublesome and needs a special guide, and then there is serving it on SwaggerUI.

Downloading SwaggerUI files

SwaggerUI can be downloaded from their GitHub Repo. Once downloaded, place the content of dist folder somewhere in your Go project. For example, swaggerui.

After that, move swagger.json file to swaggerui folder, and inside index.html change url to ./swagger.json (url: "./swagger.json").

Serve using net/http

fs := http.FileServer(http.Dir("./swaggerui"))
http.Handle("/swaggerui/", http.StripPrefix("/swaggerui/", fs))

Serve using Gorilla Mux (commit)

fs := http.FileServer(http.Dir("./swaggerui/"))
r.PathPrefix("/swaggerui/").Handler(http.StripPrefix("/swaggerui/", fs))

Serve using Echo (commit)

r.Static("/swaggerui", "cmd/api/swaggerui")

Serve using Gin (commit)

r.Static("/swaggerui/", "cmd/api/swaggerui")

End result:

A better approach

One of the greatest advantages of Go is that compiles all the source code into a single binary. If you follow the approach of putting all html/css/js files into your project folder, those won’t be compiled into Go’s binary. You’ll have to deploy swaggerui folder somewhere next to the Go binary and then set the correct path.

Using a 3rd part library, swaggerui can be compiled together with rest of the source code during build. For this, I’m using Statik, but there are plenty of alternatives such as Packr.

With statik, you first run their command to build a go file from your static files:

statik -src=/Users/ribice/go/src/github.com/ribice/golang-swaggerui-example/cmd/swaggerui

A new folder statik will be created, and inside a single go file, static.go. It’s unreadable, so don’t bother with that.

Afterwards, you’ll need the following:

_ "github.com/ribice/golang-swaggerui-example/cmd/swaggerui" // path to generated statik.go
statikFS, err := fs.New()
if err != nil {
    panic(err)
}
staticServer := http.FileServer(statikFS)

Static server is a HTTP handle, so you can serve it easily using Mux or net/http

sh := http.StripPrefix("/swaggerui/", staticServer)
router.PathPrefix("/swaggerui/").Handler(sh)

An example commit is available HERE.

With Echo and Gin, you have to wrap the http handler into their custom ones. For example:

sh := http.StripPrefix("/swaggerui/", staticServer)
eh := echo.WrapHandler(sh)
e.GET("/swaggerui", eh)

2018 © Emir Ribic - Some rights reserved; please attribute properly and link back. Code snippets are MIT Licensed

Powered by Hugo & Kiss.