1、安裝與配置html
- 下載與安裝
- 添加環境變量
2、開始第一個 swagger 案例git
- swagger 初始化
- 聲明 API 接口
- 生成接口代碼
- 添加新的功能接口
- 代碼完善
附件中下載 swagger 執行包,或者從 go-swaager 官網下載,根據 OS 選擇合適的版本:github
這裏咱們下載Windows 64版本的 swagger_windows_amd64.exe
json
將 swagger_windows_amd64.exe
重命名成 swagger.exe
, 而後將該軟件放到 Go 安裝的根目錄的 bin下 $GOROOT/bin
windows
新建一個 swagger_uac
空文件夾,進入文件夾中(PS:如下命令都在 Git
中運行,Git 配置):api
$ 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
初始化成功:app
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
檢查一下是否規範:dom
$ 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 調用接口: