Overview
In our development, debugging interfaces, testing interfaces, and providing interface documents to the front-end are all very frequent tasks. So, what methods and tools do we need to implement these tasks?
Swagger, or OpenAPI
Let us first understand what Swagger is and what OpenAPI is.
What is OpenAPI
OpenAPI is the global standard for writing RESTful APIs.
It's a specification that allows developers around the world to standardize the design of APIs and follow to all security, versioning, error handling, and other best practices when writing REST APIs from scratch.
Rather than just starting from the scratch, even existing APIs can be find-tuned to comply with global standard.
Furthermore, following established standards when developing products can be highly beneficial.
Originally, OpenAPI was called the Swagger specification.
Swagger propose best practices for building APIs, and these best practices the OpenAPI specification.
Tools like SwaggerHub help developers build APIs in a browser-based editor, comply with standards, and have complete control over the design process.
Using tools like Swagger Inspector, we can also generate our own API specifications and pass them on to other teams in the organizations.
For further information, please view the OpenAPI specification here.
What is Swagger
OpenAPI is a specification for writing API documents.
However, it's very troublesome to manually write OpenAPI specification documents. So, Swagger is a toolset that implements the OpenAPI specification.
Official website: swagger.io
Toolset included with Swagger:
- Swagger Editor : Swagger Editor allows editing OpenAPIspecifications in YAML in the browser and previewing the document in real time.
- Swagger UI : Swagger UI is a collection of HTML, Javascript, and CSS assets that can dynamically generate beautiful documentation from OAS-compliant APIs.
- Swagger Codegen : Allows automatic generation of API client libraries (SDK generation), server stubs and documentation according to the OpenAPIspecification.
- Swagger Parser : Standalone library for parsing OpenAPIdefinitions from Java.
- Swagger Core : Java-related library for creating, consuming, and consuming OpenAPIdefinitions.
- Swagger Inspector (Free) : API testing tool that allows you to verify your API and generate OpenAPIdefinitions from existing APIs.
- SwaggerHub (free and commercial) : API design and documentation, built for teams using OpenAPI.
How to integrate Swagger into Go-Micro
First of all, what we need to understand is: the only way to integrate Swagger in the project is to integrate it through the Swagger UI.
Swagger UI relies on reading API documents in json or yaml format of OpenAPI. This document is not read by humans, but by Swagger UI.
Similarly, it's not written by humans, but is generated by a generator.
Therefore, first we need to understand how the API documents are generated.
How are API documents generated?
Because Go-Micro relies on Protobuf and gRPC to design APIs, we can generate them with relevant generator tools.
Protobuf is a DSL language that requires a tool called protoc to compile and convert the API into the target language.
And its specific tools are implemented by plug-ins.
There are currently two OpenAPI generation plug-ins written in Go:
- OpenAPIv2 generator: protoc-gen-openapiv2
- OpenAPIv3 generator: protoc-gen-openapi
We can install it with the following command:
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest
go install github.com/google/gnostic/cmd/protoc-gen-openapi@latest
The directly generated command is quite simple. For example:
Generate OpenAPI v2 json documentation:
protoc --proto_path=. --openapiv2_out=paths=source_relative:../ --openapiv2_opt logtostderr=true --openapiv2_opt json_names_for_fields=true ./*.proto
Generate OpenAPI v3 yaml documentation:
protoc --proto_path=. --openapi_out=naming=json=paths=source_relative:../ ./*.proto
However, it's very inconvenient to use commands directly. We can use a tool called Buf.Build for engineering generation.
Installing Buf.build is a simple task:
go install github.com/bufbuild/buf/cmd/buf@latest
Then we need to create buf.work.yaml, buf.yaml, buf.gen.yaml and other configuration files in the root directory of the project.
This article will not explain in detail how to configure these configuration files.
You can find tutorials to learn by yourself.
This article only focuses on the relevant knowledge of generating OpenAPI.
To generate OpenAPI, we also need to create a configuration file buf.openapi.gen.yaml and place it in the same directory as proto. For example:
version: v1
managed:
  enabled: false
plugins:
  # generate openapi v2 json doc
#  - name: openapiv2
#    out: ../docs
#    opt:
#      - json_names_for_fields=true
#      - logtostderr=true
  # generate openapi v3 yaml doc
  - name: openapi
    out: ./app/admin/service/cmd/server/assets
    opt:
      - naming=json
      - depth=2
      - paths=source_relative
Then, we can use the following command in the root project directory to generate:
buf generate --path api/admin/service/v1 --template api/admin/service/v1/buf.openapi.gen.yaml
Finally, under this directory ./app/admin/service/cmd/server/assets, a file with the name openapi.yam will be generated.
How to introduce the openapi.yaml file into Swagger UI?
Yes, it's about integrating Swagger UI.
In order to do this, We need to do a few things:
- Generate OpenAPIdocuments fromBuf, compile and run the program and write it intoMakefile.
- Use the features of Golang Embedding Filesto embedopenapi.yamlit into the service program.
- Integrate Swagger UIinto the project and read embeddedopenapi.yamldocumentation.
So, we first start writing the Makefile:
# generate protobuf api go code
api:
    buf generate
# generate OpenAPI v3 docs.
openapi:
    buf generate --path api/admin/service/v1 --template api/admin/service/v1/buf.openapi.gen.yaml
    buf generate --path api/front/service/v1 --template api/front/service/v1/buf.openapi.gen.yaml
# run application
run: api openapi
    @go run ./cmd/server -conf ./configs
In this way, we only need to run make openapi to generate OpenAPI.
When debugging and running, enter the command make run to generate OpenAPI and run the program.
The Makefile is written, now we go to this directory ./app/admin/service/cmd/server/assets, and we create a code file named assets.go:
package assets
import _ "embed"
//go:embed openapi.yaml
var OpenApiData []byte
In this way, we embedded the openapi.yaml file into the program.
Finally, we need to integrate Swagger UI. I've packaged a project for this, to use it we need:
go get -u github.com/devexps/go-swagger-ui
Call the method in the package where the HTTP server is created:
package server
import (
    rest "github.com/devexps/go-micro/v2/transport/http"
    swaggerUI "github.com/devexps/go-swagger-ui"
    "demo-project/app/admin/service/cmd/server/assets"
)
func NewHTTPServer() *rest.Server {
    srv := CreateHttpServer()
    swaggerUI.RegisterSwaggerUIServerWithOption(
        srv,
        swaggerUI.WithTitle("Admin Service"),
        swaggerUI.WithMemoryData(assets.OpenApiData, "yaml"),
    )
}
From there we are done!
If the port of the API service is 8080, then we can click the link to access the Swagger UI.
http://localhost:8080/docs/

At the same time, the openapi.yaml file can also be accessed online:
http://localhost:8080/docs/openapi.yaml

Conclusion
As a programmer, laziness is a virtue in my opinions, because if you want to be lazy, you must try your best to improve the process, create tools, and automate what ever can be automated.
The integration of Swagger UI has indeed reduced the workload of mine and the team at work and improved development efficiency.
If you still don't understand anything about Go-Micro integrating Swagger UI, I have an open source project with complete application code for you: