OpenAPI

什么是OpenAPI

Swagger 是一套围绕 OpenAPI 规范构建的开源工具,可帮助我们设计,构建,记录和使用 REST API。

OpenAPI 规范(前名称为 Swagger 规范)是 REST API 的 API 描述格式。包括:

  • 可用端点 ( 例如 /users) 以及每个 endpoint 上的操作 (例如 GET /users, POST /users)
  • 操作参数,每个操作的输入和输出
  • 认证方法
  • 联系信息,许可证,使用条款等其他信息。

什么是 Swagger?

Swagger 是一组围绕 OpenAPI 规范构建的开源工具,有助于用户设计,构建,记录和使用 REST API,支持整个 API 生命周期的开发,从设计和文档到测试和部署。

使用 Swagger 的目的

  1. 标准化文档格式:Swagger (OpenAPI) 采用了准化 API 文档格式。通过使用 Swaggo(将注释转换为 Swagger2.0文档的包) 生成 Swagger 文档,Swagger 的结构化格式的文档,使开发人员更容易理解产品的 API 交互。
  2. 交互式文档体验:Swagger UI 与 Swaggo 集成,提供交互式且用户友好的界面,用于测试 API。Swaggo提供了一个自动生成的界面,允许开发人员浏览 Endpoint,查看请求/响应示例,甚至可以直接从文档执行 API 请求。这种交互式体验可提高开发人员的工作效率并加速 API 的采用。
  3. 自动且最新的文档:Swaggo 可自动从用户的 Go 代码生成 API 文档。这种自动化无需手动维护单独的文档文件。Swaggo 直接从用户的代码库中提取信息,包括 endpoint 详细信息,请求/响应模型和注释。使用这种方法可确保用户的 API 文档随着代码的更新而保持最新。

Swagger 与 Gin 的集成

拉取 Swaggo

使用如下命令下载swag

bash
1
$ go install github.com/swaggo/swag/cmd/swag

与 Gin 的集成

添加通用注释

swaggo 中包含两种注释,通用注释与 API 注释,通用注释是用于程序 main.go 中,标记文档的信息,API 注释是用于标注每个接口的信息。

  1. 下载相关包
bash
1
2
3
$ go install github.com/swaggo/swag/cmd/swag
$ go get -v github.com/swaggo/gin-swagger # gin-swagger middleware
$ go get -v github.com/swaggo/files # swagger embed files
  1. 在项目 main.go 源代码中添加通用的 API 注释:
go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// @title           Swagger Example API
// @version         1.0
// @description     This is a sample server celler server.
// @termsOfService  http://swagger.io/terms/

// @contact.name   API Support
// @contact.url    http://www.swagger.io/support
// @contact.email  support@swagger.io

// @license.name  Apache 2.0
// @license.url   http://www.apache.org/licenses/LICENSE-2.0.html

// @host      localhost:8080
// @BasePath  /api/v1

// @securityDefinitions.basic  BasicAuth

// @externalDocs.description  OpenAPI
// @externalDocs.url          https://swagger.io/resources/open-api/
func main() {
    r := gin.Default()
...
}

为 Swagger Docs 添加路由

以将中间件添加到您的 Gin 应用程序中。在您的路由函数中或者主函数中,添加如下下代码:

此代码为 Swagger UI 设置了一条路由,并告诉它在指定的 URL 处查找 Swagger 文档。

go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 默认路由
r := gin.Default()
url := ginSwagger.URL("http://localhost:8080/swagger/doc.json")
r.GET(" /swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
// 路由组
// 如果已存在路由组,可以在对应注册路由的函数中添加 docs 路径
func RegisteredRouter(e *gin.Engine) {
    e.Handle("GET", "/swagger/*any",
        ginSwagger.WrapHandler(swaggerFiles.Handler, ginSwagger.URL("/swagger/doc.json")))
...
}

向 Gin API 服务器添加 API 注释

go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// ShowAccount godoc
// @Summary      Show an account
// @Description  get string by ID
// @Tags         accounts
// @Accept       json
// @Produce      json
// @Param        id   path      int  true  "Account ID"
// @Success      200  {object}  model.Account
// @Failure      400  {object}  httputil.HTTPError
// @Failure      404  {object}  httputil.HTTPError
// @Failure      500  {object}  httputil.HTTPError
// @Router       /accounts/{id} [get]
func (c *Controller) ShowAccount(ctx *gin.Context) {

生成 Swagger 文档

将注释添加到代码后,可以通过运行以下命令生成 Swagger 文档

bash
1
$ swag init -g cmd/main.go --output ./docs/  --packageName docs

此命令将会在项目中 docks 文件夹中生成一个文件 doc.json 。我们之前添加的中间件将使用此文件在 Swagger UI 中显示文档。

确保导入了生成的包 docs/docs.go 文件,这样特定的配置文件才会被初始化。如果通用 API 注释没有写在 main.go 中,可以使用 -g 参数来告知 swag-cli

bash
1
$ swag init -g http/api.go

访问 swagger 文档

在完成上述步骤后,可以浏览器中访问 http://{project_domain}/swagger/index.html,来查看 swagger 文档,这个路径取决于在 gin 路由里配置的路径。

swagger 注释

通用 API 注释

注释说明示例
title必填 应用程序的名称。// @title Swagger Example API
version必填 提供应用程序API的版本。// @version 1.0
description应用程序的简短描述。// @description This is a sample server celler server.
tag.name标签的名称。// @tag.name This is the name of the tag
tag.description标签的描述。// @tag.description Cool Description
tag.docs.url标签的外部文档的URL。// @tag.docs.url https://example.com
tag.docs.description标签的外部文档说明。// @tag.docs.description Best example documentation
termsOfServiceAPI的服务条款。// @termsOfService http://swagger.io/terms/
contact.name公开的API的联系信息。// @contact.name API Support
contact.url联系信息的URL。 必须采用网址格式。// @contact.url http://www.swagger.io/support
contact.email联系人/组织的电子邮件地址。 必须采用电子邮件地址的格式。// @contact.email support@swagger.io
license.name必填 用于API的许可证名称。// @license.name Apache 2.0
license.url用于API的许可证的URL。 必须采用网址格式。// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
host运行API的主机(主机名或IP地址)。// @host localhost:8080
BasePath运行API的基本路径。// @BasePath /api/v1
acceptAPI 可以使用的 MIME 类型列表。 请注意,Accept 仅影响具有请求正文的操作,例如 POST、PUT 和 PATCH。 值必须如“Mime类型”中所述。// @accept json
produceAPI可以生成的MIME类型的列表。值必须如“Mime类型”中所述。// @produce json
query.collection.format请求URI query里数组参数的默认格式:csv,multi,pipes,tsv,ssv。 如果未设置,则默认为csv。// @query.collection.format multi
schemes用空格分隔的请求的传输协议。// @schemes http https
externalDocs.descriptionDescription of the external document.// @externalDocs.description OpenAPI
externalDocs.urlURL of the external document.// @externalDocs.url https://swagger.io/resources/open-api/
x-name扩展的键必须以x-开头,并且只能使用json值// @x-example-key {“key”: “value”}

API 注释

注释描述
description操作行为的详细说明。
description.markdown应用程序的简短描述。该描述将从名为 endpointname.md 的文件中读取。
id用于标识操作的唯一字符串。在所有 API 操作中必须唯一。
tags每个 API 操作的标签列表,以逗号分隔。
summary该操作的简短摘要。
acceptAPI 可以使用的 MIME 类型列表。 请注意,Accept 仅影响具有请求正文的操作,例如 POST、PUT 和 PATCH。 值必须如 “Mime类型” 中所述。
produceAPI可以生成的MIME类型的列表。值必须如 “Mime类型” 中所述。
param用空格分隔的参数。
param name,
param type,
data type,
is mandatory?,
comment attribute(optional)
security每个 API 操作的安全性。
success以空格分隔的成功响应。return code,{param type},data type,comment
failure以空格分隔的故障响应。return code,{param type},data type,comment
response与success、failure作用相同
header以空格分隔的头字段。 return code,{param type},data type,comment
router以空格分隔的路径定义。 path,[httpMethod]
deprecatedrouter与router相同,但是是deprecated的。
x-name扩展字段必须以 x- 开头,并且只能使用 json 值。
deprecated将当前 API 操作的所有路径设置为deprecated

安全相关参数

注释描述参数示例
securitydefinitions.basicBasic auth.// @securityDefinitions.basic BasicAuth
securitydefinitions.apikeyAPI key auth.in, name// @securityDefinitions.apikey ApiKeyAuth
securitydefinitions.oauth2.applicationOAuth2 application auth.tokenUrl, scope// @securitydefinitions.oauth2.application OAuth2Application
securitydefinitions.oauth2.implicitOAuth2 implicit auth.authorizationUrl, scope// @securitydefinitions.oauth2.implicit OAuth2Implicit
securitydefinitions.oauth2.passwordOAuth2 password auth.tokenUrl, scope// @securitydefinitions.oauth2.password OAuth2Password
securitydefinitions.oauth2.accessCodeOAuth2 access code auth.tokenUrl, authorizationUrl, scope// @securitydefinitions.oauth2.accessCode OAuth2AccessCode

troubleshooting

Failed to load API definition.

引用了 swaggo 的文件必须添加下面包引用

go
1
_ "project_root_dir/cmd/docs"

failed to load api definition. not found /swagger/v1/swagger.json

指定 doc 文档路径必须写对 [ginSwagger.URL("/swagger/doc.json")]

go
1
2
3
4
5
6
7
8
9
// 默认路由
r := gin.Default()
url := ginSwagger.URL("http://localhost:8080/swagger/doc.json")
r.GET(" /swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
// 路由组
// 如果已存在路由组,可以在对应注册路由的函数中添加 docs 路径
func RegisteredRouter(e *gin.Engine) {
    e.Handle("GET", "/swagger/*any",
        ginSwagger.WrapHandler(swaggerFiles.Handler, ginSwagger.URL("/swagger/doc.json")))

cannot find type definition: api_query.UserQuery

如果参数引用了一个对象,不可以写成 &api_query.UserQuery 的格式

ParseComment error in file :missing required param comment parameters “xxx”

你的项目内其他非 API 接口的函数不能使用与 API 注释相同格式的注释

cannot find type definition: errcode.Error

Reference

[1] “Failed to load API definition” / “not yet registered swag” error when rendering docs page #830

[2] localhost:8080/swagger returns 404 page not found #2

[3] Implementing Swagger in Go Projects

[4] How to add Swagger in Golang Gin.

[5] Swagger使用的时候报错:Failed to load API definition

[6] README_zh-CN.md

[7] Golang swaggo rendering error: “Failed to load API definition” and “Fetch error doc.json”