3.7 生成接口文档
你所开发的接口有没有接口文档,你的接口文档有没有及时更新,是一个永恒的话题。在本章节我们将继续使用 Swagger 作为我们的接口文档平台,但是与第二章不同,我们的载体变成了 Protobuf,Protobuf 是强规范的,其本身就包含了字段名和字段类型等等信息,因此其会更加的简便。
在接下来的章节中,我们将继续基于同端口同 RPC 方法支持双流量(grpc-gateway 方案)的服务代码来进行开发和演示。
3.7.1 安装和下载
3.7.1.1 安装 Protoc Plugin
针对后续 Swagger 接口文档的开发和使用,我们需要安装 protoc 的插件 protoc-gen-swagger,它的作用是通过 proto 文件来生成 swagger 定义(.swagger.json),安装命令如下:
$ go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
3.7.1.2 下载 Swagger UI 文件
Swagger 提供可视化的接口管理平台,也就是 Swagger UI,我们首先需要到 https://github.com/swagger-api/swagger-ui
上将其源码压缩包下载下来,接着在项目的 third_party
目录下新建 swagger-ui
目录,将其 dist
目录下的所有资源文件拷贝到我们项目的 third_party/swagger-ui
目录中去。
3.7.2 静态资源转换
在上一步中我们已经将 Swagger UI 的资源文件拷贝到了项目的 swagger-ui 目录中,但是这时候我们的应用程序还不可以使用它,我们需要使用 go-bindata 库将其资源文件转换为 Go 代码,便于我们后续使用,安装命令如下:
$ go get -u github.com/go-bindata/go-bindata/...
接下来我们在项目的 pkg
目录下新建 swagger-ui
目录,并在项目根目录执行下述转换命令:
$ go-bindata --nocompress -pkg swagger -o pkg/swagger/data.go third_party/swagger-ui/...
在执行完毕后,应当在项目的 pkg/swagger
目录下创建了 data.go 文件。
3.7.3 Swagger UI 处理和访问
为了让刚刚转换的静态资源代码能够让外部访问到,我们需要安装 go-bindata-assetfs 库,它能够结合 net/http
标准库和 go-bindata
所生成 Swagger UI
的 Go
代码两者来供外部访问,安装命令如下:
$ go get -u github.com/elazarl/go-bindata-assetfs/...
安装完成后,我们打开启动文件 main.go,修改 HTTP Server 相关的代码,如下:
import (
assetfs "github.com/elazarl/go-bindata-assetfs"
"github.com/go-programming-tour-book/tag-service/pkg/swagger"
...
)
func runHttpServer() *http.ServeMux {
serveMux := http.NewServeMux()
serveMux.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`pong`))
})
prefix := "/swagger-ui/"
fileServer := http.FileServer(&assetfs.AssetFS{
Asset: swagger.Asset,
AssetDir: swagger.AssetDir,
Prefix: "third_party/swagger-ui",
})
serveMux.Handle(prefix, http.StripPrefix(prefix, fileServer))
return serveMux
}
在上述代码中,我们通过引用先前通过 go-bindata-assetfs 所生成的 data.go 文件中的资源信息,结合两者来对外提供 swagger-ui
的 Web UI 服务。需要注意的是,因为所生成的文件的原因,因此 swagger.Asset
和 swagger.AssetDir
的引用在 IDE 识别上(会标红)存着一定的问题,但实际程序运行是没有问题的,只需要通过命令行启动就可以了。
我们重新运行该服务,通过浏览器访问 http://127.0.0.1:8004/swagger-ui/
,查看结果如下:
以上看到的就是 Swagger UI 的默认展示界面,默认展示的是 Demo 示例(也就是输入框中的 swagger 地址),如果你已经看到如上界面,那说明一切正常。
3.7.4 Swagger 描述文件生成和读取
既然 Swagger UI 已经能够看到了,那我们自己的接口文档又如何读取呢,其实刚刚在上一步,你可以看到默认示例,读取的是一个 swagger.json 的远程地址,也就是只要我们本地服务中也有对应的 swagger.json,就能够展示我们的服务接口文档了。
因此我们先需要进行 swagger 定义文件的生成,我们在项目根目录下执行以下命令:
$ protoc -I/usr/local/include -I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--swagger_out=logtostderr=true:. \
./proto/*.proto
执行完毕后你会发现 proto 目录下会多处 common.swagger.json 和 tag.swagger.json 两个文件,文件内容是对应的 API 描述信息。
接下来我们需要让浏览器能够访问到我们本地所生成的 swagger.json,也就是需要有一个能够访问本地 proto 目录下的.swagger.json 的文件服务,我们继续修改 main.go 文件,如下:
func runHttpServer() *http.ServeMux {
...
serveMux.Handle(prefix, http.StripPrefix(prefix, fileServer))
serveMux.HandleFunc("/swagger/", func(w http.ResponseWriter, r *http.Request) {
if !strings.HasSuffix(r.URL.Path, "swagger.json") {
http.NotFound(w, r)
return
}
p := strings.TrimPrefix(r.URL.Path, "/swagger/")
p = path.Join("proto", p)
http.ServeFile(w, r, p)
})
return serveMux
}
我们重新运行该服务,通过浏览器访问 http://127.0.0.1:8004/swagger/tag.swagger.json
,查看能够成功得到所生成的 API 描述信息。
3.7.5 查看接口文档
接下来我们只需要把想要查看的 swagger.json 的访问地址,填入输入框中,点击“Explore”就可以查看到对应的接口信息了,如下图:
3.7.6 小结
至此,我们就完成了 Swagger 文档的生成和使用,而目前使用上虽然是基于每一个服务运行起来的 Swagger 站点,但而在实际的环境中,也可以让每个服务仅提供 Swagger 定义,接着在统一的平台提供 Swagger 站点来读取 Swagger 定义,这样子就不需要每一个服务都运行 Swagger 站点了,同时由于入口统一了,鉴权也能在这基础上完成。