一、安装与配置
- 下载与安装
- 添加环境变量
二、开始第一个 swagger 案例
- swagger 初始化
- 声明 API 接口
- 生成接口代码
- 添加新的功能接口
- 代码完善
附件中下载 swagger 执行包,或者从 go-swaager 官网下载,根据 OS 选择合适的版本:
这里我们下载Windows 64版本的 swagger_windows_amd64.exe
将 swagger_windows_amd64.exe
重命名成 swagger.exe
, 然后将该软件放到 Go 安装的根目录的 bin下 $GOROOT/bin
新建一个 swagger_uac
空文件夹,进入文件夹中(PS:以下命令都在 Git
中运行,Git 配置):
$ mkdir swagger_uac
$ cd swagger_uac
在 Git 中输入以下命令:
$ swagger init spec > --title "User Alarm Center" > --description "A Swagger Example" > --version 1.0.0 > --scheme http > --consumes application/io.goswagger.examples.uac.v1+json > --produces application/io.goswagger.examples.uac.v1+json
初始化成功:
2020/12/17 15:05:16 creating specification document in D:\runtime\0others\swagger_uac\swagger.yml
此时, swagger_uac
文件夹中自动生成了一个 swagger.yml
文件:
consumes:
- application/io.goswagger.examples.uac.v1+json
info:
description: A Swagger Example
title: User Alarm Center
version: 1.0.0
paths: {}
produces:
- application/io.goswagger.examples.uac.v1+json
schemes:
- http
swagger: "2.0"
不管是手动修改,还是自动生成的 yam 文件,都需要用 $ swagger validate ./swagger.yml
检查一下是否规范:
$ swagger validate ./swagger.yml
2020/12/17 15:13:14
The swagger spec at "./swagger.yml" is valid against swagger specification 2.0
上面我们已经生成了一个框架 yam 文件,现在向文件中加入结构体对象信息:
---
definitions:
item:
type: object
required:
- description
properties:
id:
type: integer
format: int64
readOnly: true
description:
type: string
minLength: 1
completed:
type: boolean
该 item
中定义了 3 个字段:id,description,completed。上面对它们的数据类型和字段限制进行了基本定义:readOnly 是否只读,minLength 最小长度。
然后,我们再向 yam 文件中加入 API 接口信息:
---
paths:
/:
get:
tags:
- alarms
parameters:
- name: since
in: query
type: integer
format: int64
- name: limit
in: query
type: integer
format: int32
default: 20
responses:
200:
description: list of alarm operations
schema:
type: array
items:
$ref: "#/definitions/item"
UAC 是告警模块,所以我们定义一个 GET/
方法的 API 接口,标签为 alarms
。入参 since
为告警查询的最小 ID 值, limit
限制查询的条数,默认一次查询 20 条。响应码定义为 200,返回体是一个 array,这个 array 引用了我们刚才定义的结构体对象 $ref: "#/definitions/item"
。
为了实现接口的最小功能集,我们还应该捕获接口的错误返回。接下来,我们再定义一个 error
结构体对象,对象中有错误码和错误信息两个字段:
---
definitions:
error:
type: object
required:
- message
properties:
code:
type: integer
format: int64
message:
type: string
修改接口的 yam
定义,当响应码不为 200 时,返回 error
对象:
---
paths:
/:
get:
tags:
- alarms
parameters:
- name: limit
in: query
type: integer
format: int32
default: 20
responses:
200:
description: list of alarm operations
schema:
type: array
items:
$ref: "#/definitions/item"
default:
description: generic error response
schema:
$ref: "#/definitions/error"
此时,swagger.yam 中的所有代码为:
consumes:
- application/io.goswagger.examples.uac.v1+json
info:
description: A Swagger Example
title: User Alarm Center
version: 1.0.0
paths: {}
produces:
- application/io.goswagger.examples.uac.v1+json
schemes:
- http
swagger: "2.0"
paths:
/:
get:
tags:
- alarms
parameters:
- name: since
in: query
type: integer
format: int64
- name: limit
in: query
type: integer
format: int32
default: 20
responses:
200:
description: list of alarm operations
schema:
type: array
items:
$ref: "#/definitions/item"
default:
description: generic error response
schema:
$ref: "#/definitions/error"
definitions:
item:
type: object
required:
- description
properties:
id:
type: integer
format: int64
readOnly: true
description:
type: string
minLength: 1
completed:
type: boolean
error:
type: object
required:
- message
properties:
code:
type: integer
format: int64
message:
type: string
再次校验:
$ swagger validate ./swagger.yml
2020/12/17 16:11:16
The swagger spec at "./swagger.yml" is valid against swagger specification 2.0
先引入 gomod 模块依赖管理工具, 然后通过 yam 文件生成框架代码:
$ go mod init uac
go: creating new go.mod: module uac
$ swagger generate server -A uac -f ./swagger.yml
2020/12/17 17:06:45 validating spec D:\runtime\0others\swagger_uac\swagger.yml
2020/12/17 17:06:45 preprocessing spec with option: minimal flattening
2020/12/17 17:06:45 building a plan for generation
2020/12/17 17:06:45 generation target ./
...
2020/12/17 17:06:45 Generation completed!
For this generation to compile you need to have some packages in your GOPATH:
* github.com/go-openapi/runtime
* github.com/jessevdk/go-flags
You can get these now with: go get -u -f ./...
取文末的附件安装包,或从官网下载。安装 tree,将安装文件夹 /bin/ 目录下的 tree.exe
复制到 Git 安装的 usr 目录的 bin下:
重新打开 Git,查看 tree 是否安装成功:
$ tree --version
tree v1.5.2.2 (c) 1996 - 2009 by Steve Baker, Thomas Moore, Francesc Rocher, Kyosuke Tokoro
查看当前的目录结构:
$ tree
.
|-- cmd
| `-- uac-server
| `-- main.go
|-- go.mod
|-- models
| |-- error.go
| `-- item.go
|-- restapi
| |-- configure_uac.go
| |-- doc.go
| |-- embedded_spec.go
| |-- operations
| | |-- alarms
| | | |-- get.go
| | | |-- get_parameters.go
| | | |-- get_responses.go
| | | `-- get_urlbuilder.go
| | `-- uac_api.go
| `-- server.go
`-- swagger.yml
6 directories, 14 files
一个个文件夹看:
cmd/uac-server:文件夹名称根据上面命令的 -A 后的参数 uac 加上 server 生成
models:yam 文件中定义的结构体对象
restapi:根据 swagger 规范中的 paths 属性生成,tags 将操作分组到包中
此时可以启动服务器,首先安装二进制文件:
$ go install ./cmd/uac-server/
go: finding module for package github.com/jessevdk/go-flags
go: finding module for package github.com/go-openapi/loads
...
运行前, 我们先用 help
命令看一下这个服务的功能:
$ uac-server --help
Usage:
C:\Users\y30002195\go\bin\uac-server.exe [OPTIONS]
A Swagger Example
Application Options:
/scheme: the listeners to enable, this can be repeated and
defaults to the schemes in the swagger spec
/cleanup-timeout: grace period for which to wait before killing idle
connections (default: 10s)
/graceful-timeout: grace period for which to wait before shutting down
the server (default: 15s)
/max-header-size: controls the maximum number of bytes the server will
read parsing the request header‘s keys and values,
including the request line. It does not limit the
size of the request body. (default: 1MiB)
/socket-path: the unix socket to listen on (default:
/var/run/uac.sock)
/host: the IP to listen on (default: localhost) [%HOST%]
/port: the port to listen on for insecure connections,
defaults to a random value [%PORT%]
/listen-limit: limit the number of outstanding requests
/keep-alive: sets the TCP keep-alive timeouts on accepted
connections. It prunes dead TCP connections ( e.g.
closing laptop mid-download) (default: 3m)
/read-timeout: maximum duration before timing out read of the
request (default: 30s)
/write-timeout: maximum duration before timing out write of the
response (default: 60s)
/tls-host: the IP to listen on for tls, when not specified it‘s
the same as --host [%TLS_HOST%]
/tls-port: the port to listen on for secure connections,
defaults to a random value [%TLS_PORT%]
/tls-certificate: the certificate to use for secure connections
[%TLS_CERTIFICATE%]
/tls-key: the private key to use for secure connections
[%TLS_PRIVATE_KEY%]
/tls-ca: the certificate authority file to be used with
mutual tls auth [%TLS_CA_CERTIFICATE%]
/tls-listen-limit: limit the number of outstanding requests
/tls-keep-alive: sets the TCP keep-alive timeouts on accepted
connections. It prunes dead TCP connections ( e.g.
closing laptop mid-download)
/tls-read-timeout: maximum duration before timing out read of the
request
/tls-write-timeout: maximum duration before timing out write of the
response
Help Options:
/? Show this help message
/h, /help Show this help message
如果我们现在运行应用程序,默认情况下,它将在随机端口启动。我们也可以通过命令行参数或 port env
变量配置端口(见下文)。
$ uac-server
2020/12/17 17:53:36 Serving uac at http://127.0.0.1:57294
另起一个 Git,或者使用接口调用工具访问服务地址:
$ curl -i http://127.0.0.1:53472
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 52 100 52 0 0 52000 0 --:--:-- --:--:-- --:--:-- 52000HTTP/1.1 501 Not Implemented
Content-Type: application/io.goswagger.examples.uac.v1+json
Date: Thu, 17 Dec 2020 11:06:36 GMT
Content-Length: 52
"operation alarms.Get has not yet been implemented"
正如你看到的那样,调用该接口会返回 501 (接口未实现)。为了让当前 API 实现真正的可用性,我们需要从逻辑上实现它。与此同时,我们还可以加一个告警新增的功能 post
:
---
paths:
/:
post:
tags:
- alarms
operationId: addAlarm
parameters:
- name: body
in: body
schema:
$ref: "#/definitions/item"
responses:
201:
description: Created
schema:
$ref: "#/definitions/item"
default:
description: error
schema:
$ref: "#/definitions/error"
注意,我们新增了 operationId
属性,它可以在 tags 包下面生成带属性名称的 Go 文件。
接下来,我们再定义一个删除的功能:
---
paths:
/{id}:
delete:
tags:
- alarms
operationId: deleteAlarm
parameters:
- type: integer
format: int64
name: id
in: path
required: true
responses:
204:
description: Deleted
default:
description: error
schema:
$ref: "#/definitions/error"
最后,定义修改的功能(由于/{id} 路径是 DELETE 和 PUT 共享的,因此它们可以共享一个参数定义):
---
paths:
/{id}:
parameters:
- type: integer
format: int64
name: id
in: path
required: true
put:
tags:
- alarms
operationId: updateAlarm
parameters:
- name: body
in: body
schema:
$ref: "#/definitions/item"
responses:
‘200‘:
description: OK
schema:
$ref: "#/definitions/item"
default:
description: error
schema:
$ref: "#/definitions/error"
delete:
# elided for brevity
再来看看完整的 API 规范(注意缩进不要弄错):
consumes:
- application/io.goswagger.examples.uac.v1+json
info:
description: A Swagger Example
title: User Alarm Center
version: 1.0.0
paths: {}
produces:
- application/io.goswagger.examples.uac.v1+json
schemes:
- http
- https
swagger: "2.0"
paths:
/:
get:
tags:
- alarms
operationId: getAlarms
parameters:
- name: since
in: query
type: integer
format: int64
- name: limit
in: query
type: integer
format: int32
default: 20
responses:
200:
description: list of alarm operations
schema:
type: array
items:
$ref: "#/definitions/item"
default:
description: generic error response
schema:
$ref: "#/definitions/error"
post:
tags:
- alarms
operationId: addAlarm
parameters:
- name: body
in: body
schema:
$ref: "#/definitions/item"
responses:
201:
description: Created
schema:
$ref: "#/definitions/item"
default:
description: error
schema:
$ref: "#/definitions/error"
/{id}:
parameters:
- type: integer
format: int64
name: id
in: path
required: true
put:
tags:
- alarms
operationId: updateAlarm
parameters:
- name: body
in: body
schema:
$ref: "#/definitions/item"
responses:
‘200‘:
description: OK
schema:
$ref: "#/definitions/item"
default:
description: error
schema:
$ref: "#/definitions/error"
delete:
tags:
- alarms
operationId: deleteAlarm
parameters:
- type: integer
format: int64
name: id
in: path
required: true
responses:
204:
description: Deleted
default:
description: error
schema:
$ref: "#/definitions/error"
definitions:
item:
type: object
required:
- description
properties:
id:
type: integer
format: int64
readOnly: true
description:
type: string
minLength: 1
completed:
type: boolean
error:
type: object
required:
- message
properties:
code:
type: integer
format: int64
message:
type: string
swagger.yam
文件校验:
$ swagger validate ./swagger.yml
2020/12/17 21:35:42
The swagger spec at "./swagger.yml" is valid against swagger specification 2.0
再次生成 API 代码文件:
$ swagger generate server -A uac -f ./swagger.yml
2020/12/17 21:37:14 validating spec D:\runtime\0others\swagger_uac\swagger.yml
2020/12/17 21:37:14 preprocessing spec with option: minimal flattening
...
2020/12/17 21:37:14 Generation completed!
For this generation to compile you need to have some packages in your GOPATH:
* github.com/go-openapi/runtime
* github.com/jessevdk/go-flags
You can get these now with: go get -u -f ./...
查看文件目录:
$ tree
.
|-- cmd
| `-- uac-server
| `-- main.go
|-- go.mod
|-- go.sum
|-- models
| |-- error.go
| `-- item.go
|-- restapi
| |-- configure_uac.go
| |-- doc.go
| |-- embedded_spec.go
| |-- operations
| | |-- alarms
| | | |-- add_alarm.go
| | | |-- add_alarm_parameters.go
| | | |-- add_alarm_responses.go
| | | |-- add_alarm_urlbuilder.go
| | | |-- delete_alarm.go
| | | |-- delete_alarm_parameters.go
| | | |-- delete_alarm_responses.go
| | | |-- delete_alarm_urlbuilder.go
| | | |-- get.go
| | | |-- get_alarms.go
| | | |-- get_alarms_parameters.go
| | | |-- get_alarms_responses.go
| | | |-- get_alarms_urlbuilder.go
| | | |-- get_parameters.go
| | | |-- get_responses.go
| | | |-- get_urlbuilder.go
| | | |-- update_alarm.go
| | | |-- update_alarm_parameters.go
| | | |-- update_alarm_responses.go
| | | `-- update_alarm_urlbuilder.go
| | `-- uac_api.go
| `-- server.go
`-- swagger.yml
6 directories, 31 files
新文件生成了,但我们还需要做一点改动,打开 restapi/configure_todo_list.go
文件。首先,在第一个函数前新增两个全局变量:
// API 全程需要的变量
var items = make(map[int64]*models.Item)
var lastID int64
先在 configureAPI
函数中实现最简单的 delete 方法:
api.AlarmsDeleteAlarmHandler = alarms.DeleteAlarmHandlerFunc(func(params alarms.DeleteAlarmParams) middleware.Responder {
delete(items, params.ID)
return alarms.NewDeleteAlarmNoContent()
})
如上所示:我们虽然修改了查询告警
getAlarm
接口的规范,但是旧的代码不会被覆盖,所以我们先把之前的代码删除掉,并添加增、改、查的代码。
新增的全部代码:
// API 全程需要的变量
var items = make(map[int64]*models.Item)
var lastID int64
var itemsLock = &sync.Mutex{}
func newItemID() int64 {
return atomic.AddInt64(&lastID, 1)
}
func addItem(item *models.Item) error {
if item == nil {
return errors.New(500, "item must be present")
}
itemsLock.Lock()
defer itemsLock.Unlock()
newID := newItemID()
item.ID = newID
items[newID] = item
return nil
}
func updateItem(id int64, item *models.Item) error {
if item == nil {
return errors.New(500, "item must be present")
}
itemsLock.Lock()
defer itemsLock.Unlock()
_, exists := items[id]
if !exists {
return errors.NotFound("not found: item %d", id)
}
item.ID = id
items[id] = item
return nil
}
func deleteItem(id int64) error {
itemsLock.Lock()
defer itemsLock.Unlock()
_, exists := items[id]
if !exists {
return errors.NotFound("not found: item %d", id)
}
delete(items, id)
return nil
}
func allItems(since int64, limit int32) (result []*models.Item) {
result = make([]*models.Item, 0)
for id, item := range items {
if len(result) >= int(limit) {
return
}
if since == 0 || id > since {
result = append(result, item)
}
}
return
}
func configureAPI(api *operations.UacAPI) http.Handler {
...
api.AlarmsAddAlarmHandler = alarms.AddAlarmHandlerFunc(func(params alarms.AddAlarmParams) middleware.Responder {
if err := addItem(params.Body); err != nil {
return alarms.NewAddAlarmDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return alarms.NewAddAlarmCreated().WithPayload(params.Body)
})
api.AlarmsDeleteAlarmHandler = alarms.DeleteAlarmHandlerFunc(func(params alarms.DeleteAlarmParams) middleware.Responder {
if err := deleteItem(params.ID); err != nil {
return alarms.NewDeleteAlarmDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return alarms.NewDeleteAlarmNoContent()
})
api.AlarmsUpdateAlarmHandler = alarms.UpdateAlarmHandlerFunc(func(params alarms.UpdateAlarmParams) middleware.Responder {
if err := updateItem(params.ID, params.Body); err != nil {
return alarms.NewUpdateAlarmDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
}
return alarms.NewUpdateAlarmOK().WithPayload(params.Body)
})
api.AlarmsGetAlarmsHandler = alarms.GetAlarmsHandlerFunc(func(params alarms.GetAlarmsParams) middleware.Responder {
mergedParams := alarms.NewGetAlarmsParams()
mergedParams.Since = swag.Int64(0)
if params.Since != nil {
mergedParams.Since = params.Since
}
if params.Limit != nil {
mergedParams.Limit = params.Limit
}
return alarms.NewGetAlarmsOK().WithPayload(allItems(*mergedParams.Since, *mergedParams.Limit))
})
...
}
再次安装,运行服务:
$ go install ./cmd/uac-server/
$ uac-server
2020/12/17 22:25:00 Serving uac at http://127.0.0.1:63192
调用接口,查询成功:
$ curl -i http://127.0.0.1:63192
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3 100 3 0 0 3000 0 --:--:-- --:--:-- --:--:-- 3000HTTP/1.1 200 OK
Content-Type: application/io.goswagger.examples.uac.v1+json
Date: Thu, 17 Dec 2020 14:25:30 GMT
Content-Length: 3
[]
向 uac 中连续添加 3 条告警信息,注意 json 格式为 application/io.goswagger.examples.uac.v1+json
$ curl -i http://127.0.0.1:63192 -d "{\"description\":\"message $RANDOM\"}" -H ‘Content-Type: application/io.goswagger.examples.uac.v1+json‘
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 68 100 38 100 30 38000 30000 --:--:-- --:--:-- --:--:-- 68000HTTP/1.1 201 Created
Content-Type: application/io.goswagger.examples.uac.v1+json
Date: Fri, 18 Dec 2020 01:31:23 GMT
Content-Length: 38
{"description":"message 9934","id":1}
// 继续调用两次添加命令
查询:
$ curl -i localhost:63192
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 118 100 118 0 0 18 0 0:00:06 0:00:06 --:--:-- 27HTTP/1.1 200 OK
Content-Type: application/io.goswagger.examples.uac.v1+json
Date: Fri, 18 Dec 2020 01:33:08 GMT
Content-Length: 118
[{"description":"message 9934","id":1},{"description":"message 19901","id":2},{"description":"message 16380","id":3}]
删除 ID 为 1 的告警消息:
$ curl -i localhost:63192/1 -X DELETE
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0HTTP/1.1 204 No Content
Date: Fri, 18 Dec 2020 01:37:31 GMT
查询:
$ curl -i localhost:63192
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 80 100 80 0 0 12 0 0:00:06 0:00:06 --:--:-- 18HTTP/1.1 200 OK
Content-Type: application/io.goswagger.examples.uac.v1+json
Date: Fri, 18 Dec 2020 01:37:49 GMT
Content-Length: 80
[{"description":"message 19901","id":2},{"description":"message 16380","id":3}]
修改 ID 为 3 的 message
信息:
$ curl -i localhost:63192/3 -d "{\"description\":\"message has been updated\"}" -X PUT -H ‘Content-Type: application/io.goswagger.examples.uac.v1+json‘
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 92 100 50 100 42 3125 2625 --:--:-- --:--:-- --:--:-- 5750HTTP/1.1 200 OK
Content-Type: application/io.goswagger.examples.uac.v1+json
Date: Fri, 18 Dec 2020 01:49:35 GMT
Content-Length: 50
{"description":"message has been updated","id":3}
PS:除了用命令的形式,也可用 postman 或 insomnia 调用接口:
原文:https://www.cnblogs.com/yangfx/p/14154383.html