首页 > 其他 > 详细

Go-swagger 的安装与使用

时间:2020-12-18 14:35:43      阅读:43      评论:0      收藏:0      [点我收藏+]

目录

一、安装与配置

  1. 下载与安装
  2. 添加环境变量

二、开始第一个 swagger 案例

  1. swagger 初始化
  2. 声明 API 接口
  3. 生成接口代码
  4. 添加新的功能接口
  5. 代码完善

一、安装与配置

1.下载与安装

附件中下载 swagger 执行包,或者从 go-swaager 官网下载,根据 OS 选择合适的版本:

技术分享图片

这里我们下载Windows 64版本的 swagger_windows_amd64.exe

2. 添加环境变量

swagger_windows_amd64.exe 重命名成 swagger.exe, 然后将该软件放到 Go 安装的根目录的 bin下 $GOROOT/bin

技术分享图片

二、开始第一个 Swagger 案例

1. swagger 初始化

新建一个 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

2. 声明 API 接口

上面我们已经生成了一个框架 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

3. 生成接口代码

先引入 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"

4. 添加新的功能接口

正如你看到的那样,调用该接口会返回 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

5. 代码完善

新文件生成了,但我们还需要做一点改动,打开 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 调用接口:

技术分享图片

Go-swagger 的安装与使用

原文:https://www.cnblogs.com/yangfx/p/14154383.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!