@daduizhang
2019-02-27T14:37:28.000000Z
字数 7351
阅读 1876
swagger
go
go-swagger
Swagger是一个简单但功能强大的API表达工具。它具有地球上最大的API工具生态系统,数以千计的开发人员,使用几乎所有的现代编程语言,都在支持和使用Swagger。使用Swagger生成API,我们可以得到交互式文档,自动生成代码的SDK以及API的发现特性等。
swagger: "2.0"
info:
version: 1.0.0
title: Simple API
description: A simple API to learn how to write OpenAPI Specification
schemes:
- https
host: simple.api
basePath: /openapi101
paths: {}
安装有多种方式, 介绍两个稍微常用的安装方式:
# brew
brew tap go-swagger/go-swagger
brew install go-swagger
# go get
go get -u github.com/go-swagger/go-swagger/cmd/swagger
下面我们讲解一下如何使用go-swagger,在使用之前你或许需要了解一下openAPI是做什么的,我们现在所做的认为你对openAPI有所了解。
因为我们所做的是依靠源码生成我们要的swagger文档,所以你现在要记住一个这样的命令:
# 根源源码生成一个swagger文档,他的类型可以是json或者是yaml,根据你的后缀名
swagger generate spec -o ./swagger.json/yaml
# 测试这个swagger文档是否有效
swagger validate ./swagger.json/yaml
如出现这样一段话,则表示你生成的yaml或json文件没有问题:
The swagger spec at "swagger.json/yaml" is valid against swagger specification 2.0
现在我们知道了这样的两个命令,我们就要知道如何才能生成一个合格的swagger文档呢,这时候我们就需要了解一下在源码中如何写注释,从而可以获取这些文档。
我们来看一下都有哪些形态的注释:
接下来我们会一一讲解这些具体怎么做:
这是你应该添加到项目中的第一个注释。它被用来描述你的项目名称,描述,联系电子邮件,网站,许可证等等信息。
// Package classification Petstore API.
//
// the purpose of this application is to provide an application
// that is using plain go code to define an API
//
// This should demonstrate all the possible comment annotations
// that are available to turn go code into a fully compliant swagger 2.0 spec
//
// Terms Of Service:
//
// there are no TOS at this moment, use at your own risk we take no responsibility
//
// Schemes: http, https
// Host: localhost
// BasePath: /v2
// Version: 0.0.1
// License: MIT http://opensource.org/licenses/MIT
// Contact: John Doe<john.doe@example.com> http://john.doe.com
//
// Consumes:
// - application/json
// - application/xml
//
// Produces:
// - application/json
// - application/xml
//
// Security:
// - api_key:
//
// SecurityDefinitions:
// api_key:
// type: apiKey
// name: KEY
// in: header
// oauth2:
// type: oauth2
// authorizationUrl: /oauth2/auth
// tokenUrl: /oauth2/token
// in: header
// scopes:
// bar: foo
// flow: accessCode
//
// Extensions:
// x-meta-value: value
// x-meta-array:
// - value1
// - value2
// x-meta-array-obj:
// - name: obj
// value: field
//
// swagger:meta
package classification
我们来讲一下这里面的一些参数的设定:
参数 | 介绍 |
---|---|
Terms Of Service | 描述API的一些基本信息,和一些请求的基本信息 |
Consumes | API从客户端接收的内容的默认(全局)mime类型值列表,每行一个。 |
Produces | API发送给客户端的内容的默认(全局)mime类型值列表,每行一个。 |
Schemes | http、https |
Version | 版本号 |
Host | 主机的地址 |
BasePath | API的基础路径 |
License | 许可证明 |
Contact | 联系人等信息 |
Security | api-key |
SecurityDefinitions | 一些授权的信息,比如JWT |
Extensions | 一些扩展行的信息 |
当你执行生成文档的命令时,会生成一个yaml/json文件,你应该可以看到这样的信息:
---
swagger: '2.0'
consumes:
- application/json
- application/xml
produces:
- application/json
- application/xml
schemes:
- http
- https
info:
description: "the purpose of this application is to provide an application\nthat is using plain go code to define an API\n\nThis should demonstrate all the possible comment annotations\nthat are available to turn go code into a fully compliant swagger 2.0 spec"
title: 'Petstore API.'
termsOfService: 'there are no TOS at this moment, use at your own risk we take no responsibility'
contact: {name: 'John Doe', url: 'http://john.doe.com', email: john.doe@example.com}
license: {name: MIT, url: 'http://opensource.org/licenses/MIT'}
version: 0.0.1
host: localhost
basePath: /v2
x-meta-value: value
x-meta-array:
- value1
- value2
x-meta-array-obj:
- name: obj
value: field
有两种方式两个注释你的路由,swagger:operation 和swagger:route。两者看起来都很相似,那么主要区别是什么?
把 swagger:route 看作简单 API 的短注释,它适用于没有输入参数(路径/查询参数)的 API 。那些(带有参数)的例子是 /repos/{owner} , /user/{id} 或者 /users/search?name=ribice。
// ServeAPI serves the API for this record store
func TestSwagger(c *gin.Context) {
// swagger:route GET /pets PetsUsers listPets
//
// Lists pets filtered by some parameters.
//
// This will show all available pets by default.
// You can get the pets that are out of stock
//
// Responses:
// default: genericError
// 200: someResponse
// 400: validationError
我们来解释一下swagger:route 后面的参数都是干什么的:
参数 | 介绍 |
---|---|
GET | get请求 |
/pets | 匹配的url地址 |
PetsUsers | 路由所在的空间分割标签 |
listPets | 用于此端点的请求 |
Lists pets.. | 摘要(标题)。对于swager:route注释,在第一个句号(.)前面的是标题。如果没有句号,就会没有标题并且这些文字会被用于描述。 |
This will... | 描述。对于swager:route类型注释,在第一个句号(.)后面的是描述。 |
responses | 这个端点的响应 |
default | 默认返回的错误,包含genericError(用 swagger:response 注释的模型) |
200 | 一个(成功的)响应HTTP状态 200,包含 repoResp(用 swagger:response 注释的模型) |
400 | 此端点的错误响应,包含 validationError(用 swagger:response 注释的模型) |
当你执行生成文档的命令时,会生成一个yaml/json文件,你应该可以看到这样的信息:
---
paths:
"/pets":
get:
operationId: listPets
summary: Lists pets filtered by some parameters.
description: "This will show all available pets by default.\nYou can get the pets that are out of stock"
tags:
- PetsUsers
responses:
default:
$ref: "#/responses/genericError"
200:
$ref: "#/responses/someResponse"
422:
$ref: "#/responses/validationError"
使用 Swagger:operation 可以让你使用所有OpenAPI规范,你可以描述你的复杂的端点, 如果你对细节感兴趣,你可以阅读openAPI的规范文档。
// ServeAPI serves the API for this record store
func TestSwagger(c *gin.Context) {
// swagger:operation GET /repo/{author} repos repoList
// ---
// summary: List the repositories owned by the given author.
// description: If author length is between 6 and 8, Error Not Found (404) will be returned.
// parameters:
// - name: author
// in: path
// description: username of author
// type: string
// required: true
// responses:
// "200":
// "$ref": "#/responses/reposResp"
// "404":
// "$ref": "#/responses/notFound"
我们可以看到这根我们平常写入的openAPI的文档格式一毛一样,我们来解释一下各个参数吧:
参数 | 介绍 |
---|---|
GET | get请求 |
/repo/{author} | 匹配的url地址 |
repos | 路由所在的空间分割标签 |
repoList | 用于此端点的请求,这个不存在(没有定义),但参数是强制性的,所以你可以用任何东西来替换repoList(noReq,emptyReq等) |
“---” | 这个部分下面是YAML格式的swagger规范。确保您的缩进是一致的和正确的,否则将无法正确解析。注意,如果你在YAML中定义了标签,摘要,描述或操作标签,将覆盖上述常规swagger语法中的摘要,描述,标记或操作标签。 |
生成的swagger规范中的参数:
// swagger:parameters test_demo
type BarSliceParam struct {
// a BarSlice has bars which are strings
//
// min items: 3
// max items: 10
// unique: true
// Required: true
// in: query
Name string `json:"name"`
}
ps: 此结构的字段可以使用许多注释进行修饰。对于字段名称,它使用struct字段名称,它尊重json struct字段标记以自定义名称。
我们来解释一下swagger:parameters 后面的参数都是干什么的:
参数 | 介绍 |
---|---|
test_demo | operationID, go-swagger会以此来寻找你的关联的方法 |
a BarSlice... | 这个就是你参数的描述 |
minLength | 参数最短长度 |
maxLength | 参数最大长度 |
in | 参数放在什么位置,如:body,query,path |
unique | 参数是否是唯一的 |
Required | 是否必传 |
当你执行生成文档的命令时,会生成一个yaml/json文件,你应该可以看到这样的信息:
---
operations:
"/":
get:
operationId: test_demo
parameters:
- name: name
in: query
maxLength: 10
minLength: 3
unique: true
Required: true
响应注释与参数注释非常相似。主要的区别在于,经常将响应包裹到更复杂的结构中。
一般的响应会是这样的:
{
"msg": "OK"
"code":200, // Code containing HTTP status CODE
"data":{} // Data containing actual response data
}
要使用常规响应,像上面错误响应那样的,我们需要在代码中新建一个reponse.go这种类似的文件,下面的响应用于 OK 响应(不返回任何数据):
// A ValidationError is an error that is used when the required input fails validation.
// swagger:response validationError
type ValidationError struct {
// The error message
// in: body
Body struct {
// The validation message
//
// Required: true
Message string
// An optional field name to which this validation applies
FieldName string
}
}
或者是这样的形式:
// 成功或失败返回的数据格式
// swagger:response SwaggerResponse
type SwaggerWapper struct {
// The error message
// in: body
Body ResponseMessage
}
type ResponseMessage struct {
// 返回的code码
// Required: true
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
只是生成出来的效果不一样,第一个展现的json/yaml格式会被展开:
---
responses:
validationError:
description: A ValidationError is an error that is used when the required input fails validation.
schema:
type: object
description: The error message
required:
- Message
properties:
Message:
type: string
description: The validation message
example: Expected type int
FieldName:
type: string
description: an optional field name to which this validation applies
而第二种形式的则会被建华折叠起来,如这样:
responses:
SwaggerResponse:
description: 成功或失败返回的数据格式
schema:
$ref: '#/definitions/ResponseMessage'
definitions:
ResponseMessage:
properties:
code:
description: 返回的code码
type: integer
data:
type: object
msg:
type: string
required:
- code
type: object
第二种形式更加通用,复用性很好,Swagger:response和Swagger:parameters的注释形式基本没差,就不讲解更多了。