iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 27
1
Software Development

下班加減學點Golang與Docker系列 第 27

Gin With Swagger, 懶人API Doc生成神器

API文件

每位後端RD, 在寫WebAPI時,
一定覺得寫扣還要維護API文件, 是件很繁瑣但又重要的工作.

不寫, 前端或者串接的人照三餐來問.
寫, 又很花時間還容易寫錯字.

Swagger是一個能夠快速的生產出一份API Doc的工具.

Swagger

幾乎主流語言都有支援Swagger, Go也不例外.
Swaggo/swag就是用Go撰寫的.
swag有支援gin、net/http, 剛好我們前面寫的都能用^^

安裝Swag

go get -u github.com/swaggo/swag/cmd/swag

檢查swag, 會出現版本跟指令
其實也就init跟help

swag -h

初始化swag

在專案根目錄下執行

swag init

會看到在根目錄下生出了doc資料夾, 裡面會有

  • docs.go
  • swagger.json
  • swagger.yaml

匯入包跟註冊路由

首先匯入docs包, mod名稱請改成自己的^^
小小修改一下code, SetupRouter傳入port這參數.
router也改成監聽port提供的端口.

test那邊的案例, 記得都要傳入隨便一個數字, 不然測試會跑失敗.

main.go

import (
	_ "github.com/tedmax100/gin-angular/docs"
)

func main() {
	port := 8080
	router := router.SetupRouter(port)
	router.Run(fmt.Sprintf(":%d", port))
}

SetupRouter.go

import (
    swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
)

func SetupRouter(port int) *gin.Engine {
    ...
    if mode := gin.Mode(); mode == gin.DebugMode {
		url := ginSwagger.URL(fmt.Sprintf("http://localhost:%d/swagger/doc.json", port))
		router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
    }
    ...
}

因為Swagger幾乎都是在內部網路可視的.
不然外網要是也能看得到...就都能亂打API了.
這個就把http監聽的port傳進來.
也判別gin.Mode()是不是處於debug mode.
是的話才註冊swagger要用的路由.

Swagger 註解

Swagger能產文件, 其實全靠註解.
只要遵從swagger格式寫出來的註解, 就會產生對應文檔說明.

一般說明

main.go

// @title Gin swagger
// @version 1.0
// @description Gin swagger

// @contact.name nathan.lu
// @contact.url https://tedmax100.github.io/

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

// @host localhost:8080
// schemes http
func main() { ... }

API Info

註解 描述
title 必須簡單API專案的標題或主要的業務功能
version 必須目前這專案/API的版本
description 簡單描述
tersOfService 服務條款
contact.name 作者名稱
contact.url 作者blog
contact.email 作者email
license.name 必須許可證名稱
license.url 許可證網址
host 服務名稱或者是ip
BasePath 基本URL路徑, (/api/v1, /v2...)
schemes 提供的協定, (http, https)

執行生成api doc, 並且執行api

swag init; go run main.go

打開瀏覽器輸入http://localhost:8080/swagger/index.html

如果都沒錯誤, 看到的就是這樣, 空的XD
因為還沒對每隻API寫註解.

API Operation

helloHandler.go

// @Summary 說Hello
// @Id 1
// @Tags Hello
// @version 1.0
// @produce text/plain
// @Success 200 string string 成功後返回的值
// @Router /hello [get]
func GetHello(ctx *gin.Context) {...}

// @Summary Delete Hello
// @Id 1
// @Tags Hello
// @version 1.0
// @produce text/plain
// @param id path int true "id"
// @Success 200 string string 成功後返回的值
// @Router /hello/{id} [delete]
func DeleteHello(ctx *gin.Context) { ... }

userHandler.go
在這裡新增自定義的Header, 通常我們就是放authorization token用
或其他, 只要標示是在header即可.

// @Summary User Login
// @Tags User
// @version 1.0
// @produce application/json
// @param email formData string true "email"
// @param password formData string true "password"
// @param password-again formData string true "password-again"
// @Success 200 string string 成功後返回的值
// @Router /user/login [post]
func UserLogin(ctx *gin.Context) { ... }

// @Summary Get User Info
// @Tags User
// @version 1.0
// @produce text/plain
// @param Authorization header string true "Authorization"
// @param uid path int true "uid"
// @Success 200 string string 成功後返回的值
// @Router /user/{uid} [get]
func GetUser(ctx *gin.Context) { ... }
註解 描述
summary 描述該API
tags 歸屬同一類的API的tag
accept request的context-type
produce response的context-type
param 參數按照 參數名 參數類型 參數的資料類型 是否必須 註解 (中間都要空一格)
header response header return code 參數類型 資料類型 註解
router path httpMethod

參數類型

  • query (就是拼接在url後面的query string)
  • path (url內)
  • header (表頭內)
  • body
  • formData

Data Type

  • string (string)
  • integer (int, uint, uint32, uint64)
  • number (float32)
  • boolean (bool)
  • user defined struct

再次執行生成api doc, 並且執行api

swag init; go run main.go

打開瀏覽器輸入http://localhost:8080/swagger/index.html


基本的API文件就出來了
但我還是覺得單元測試跟整合測試寫的完整點, 比較實在XD
畢竟文件只能是串接開發時參考用, 測試才能一直重複利用.
好的測試本身就是個能讀的文件(BDD).


上一篇
Go gRPC第一次接觸...
下一篇
Go 鍊結參數 LDFLAGS
系列文
下班加減學點Golang與Docker30

尚未有邦友留言

立即登入留言