(摘) Swagger 自动生成接口文档

声明:内容源自网络,版权归原作者所有。若有侵权请在网页聊天中联系我

除了它可以自动生成接口文档以外,也可以规范代码。

Github: https://github.com/swaggo/swag
中文帮助

安装自动生成工具swag: go install github.com/swaggo/swag/cmd/swag@latest

自动生成文档: swag init

我是使用的gin居多,可以先看看示例 celler。先 swag init 生成,然后go run . ,打开 http://localhost:8080/swagger/index.htm

注释 描述
description 操作行为的详细说明。
description.markdown 应用程序的简短描述。该描述将从名为endpointname.md的文件中读取。
id 用于标识操作的唯一字符串。在所有API操作中必须唯一。
tags 每个API操作的标签列表,以逗号分隔。
summary 该操作的简短摘要。
accept API 可以使用的 MIME 类型列表。 请注意,Accept 仅影响具有请求正文的操作,例如 POST、PUT 和 PATCH。 值必须如“Mime类型”中所述。
produce API可以生成的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]
x-name 扩展字段必须以x-开头,并且只能使用json值。

看示例代码,它引用了gin-swagger库,它是一个GIN的中间件用于处理swagger API。
这个中间件也比较简单,开始使用时,比较难记以上中的标记名称。
通常我们直接写函数,而这里我们就需要作一些注释,让swag工具自动生成接口。

// @BasePath /api/v1

// PingExample godoc
// @Summary ping example
// @Schemes
// @Description do ping
// @Tags example
// @Accept json
// @Produce json
// @Success 200 {string} Helloworld
// @Router /example/helloworld [get]
func Helloworld(g *gin.Context)  {
	g.JSON(http.StatusOK,"helloworld")
}
  1. swag init 它将自动生成docs目录及接口文档。

  2. 在程序中引入以上生成的docs库:import docs

  3. 引入相关库

	swaggerfiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
  1. 指定中间件: r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))

  2. 运行后即有API接口文档了: http://localhost:8080/swagger/index.html

在程序的主包中,可以添加主要的说明及参数

// @title 健康助手API
// @version 1.0
// @description 健康助手API服务器
// @termsOfService http://swagger.io/terms/

// @contact.name Ease
// @contact.url https://b.scwy.net
// @contact.email ease@scwy.net

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

// @host 127.0.0.1:8080
// @BasePath /v1

这里的host不要带http之类的喔。

似乎也可以在代码中指定

	docs.SwaggerInfo.Title = "Swagger Example API"
	docs.SwaggerInfo.Description = "This is a sample server Petstore server."
	docs.SwaggerInfo.Version = "1.0"
	docs.SwaggerInfo.Host = "petstore.swagger.io"
	docs.SwaggerInfo.BasePath = "/v2"
	docs.SwaggerInfo.Schemes = []string{"http", "https"}

swag-cli工具参数说明

swag init -h
NAME:
   swag init - Create docs.go

USAGE:
   swag init [command options] [arguments...]

OPTIONS:
   --generalInfo value, -g value          API通用信息所在的go源文件路径,如果是相对路径则基于API解析目录 (默认: "main.go")
   --dir value, -d value                  API解析目录 (默认: "./")
   --exclude value                        解析扫描时排除的目录,多个目录可用逗号分隔(默认:空)
   --propertyStrategy value, -p value     结构体字段命名规则,三种:snakecase,camelcase,pascalcase (默认: "camelcase")
   --output value, -o value               文件(swagger.json, swagger.yaml and doc.go)输出目录 (默认: "./docs")
   --parseVendor                          是否解析vendor目录里的go源文件,默认不
   --parseDependency                      是否解析依赖目录中的go源文件,默认不
   --markdownFiles value, --md value      指定API的描述信息所使用的markdown文件所在的目录
   --generatedTime                        是否输出时间到输出文件docs.go的顶部,默认是
   --codeExampleFiles value, --cef value  解析包含用于 x-codeSamples 扩展的代码示例文件的文件夹,默认禁用
   --parseInternal                        解析 internal 包中的go文件,默认禁用
   --parseDepth value                     依赖解析深度 (默认: 100)
   --instanceName value                   设置文档实例名 (默认: "swagger")

修改页面标题

	r.GET("/swagger/*any", ginSwagger.WrapHandler(
		swaggerfiles.Handler,
		func(c *ginSwagger.Config) {
			c.Title = "健康助手 API"
		},
	)) // API中间件

看到了另一种换肤方式,修改显示效果

// 初始化总路由

func Routers() *gin.Engine {
    // ...
    // 替换handler
    // Router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
    Router.GET("/swagger/*any", handleReDoc)
    // ...
}

func handleReDoc(ctx *gin.Context) {
    i := strings.LastIndex(ctx.Request.URL.Path, "/")
    if i == -1 {
        return
    }
    suffix := ctx.Request.URL.Path[i+1:]
    switch suffix {
    case "doc.json":
        // 载入swag生成的 docs/swagger.json
        data, err := ioutil.ReadFile("docs/swagger.json")
        if err != nil {
            panic("cannot open docs/swagger.json")
        }

        _, _ = ctx.Writer.Write(data)
        return
    case "index.html":
        // 这个index.html咱们得从ReDoc的github主页上拿
        // spec-url是swagger.json的URL,要改为当前项目的
        const redocIndexHTML = `<!DOCTYPE html>
        <html>
          <head>
            <title>ReDoc换皮成功</title>
            <!-- needed for adaptive design -->
            <meta charset="utf-8"/>
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
        
            <!--
            ReDoc doesn't change outer page styles
            -->
            <style>
              body {
                margin: 0;
                padding: 0;
              }
            </style>
          </head>
          <body>
            <redoc spec-url='http://127.0.0.1:1888/swagger/doc.json'></redoc>
            <script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
          </body>
        </html>`
        fmt.Println("ererer")
        _, _ = ctx.Writer.Write([]byte(redocIndexHTML))
        return
    default:
        _ = ctx.AbortWithError(http.StatusNotFound, errors.New("page not found"))
    }
}

看起来主要是页面对swagger.json文件的展示。

相关文章