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.
Read about Goch — Self hosted live-chat built with Go, NATS, Redis and Webscockets
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)
sh := http.StripPrefix("/swaggerui/", http.FileServer(http.Dir("./swaggerui/")))
r.PathPrefix("/swaggerui/").Handler(sh)
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 it all the source code can be compiled into a single binary. If you follow the approach of putting swaggerui html/css/js files in a separate folder, they won’t be compiled into a Go binary. You’ll have to deploy swaggerui
folder somewhere next to the Go binary and then set the correct path.
To achieve this a third party dependency is needed. I’m using Statik, but plenty of alternatives exist 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)