OpenAPITools 可以依據 REST API 描述檔案,自動生成服務端樁(Stub)程式碼、客戶端 SDK 程式碼,及文件等。其是社群版的 Swagger ,差異可見:OpenAPI Generator vs Swagger Codegen。
本文將從零開始設計和編寫 API 檔案,並生成 Go Gin 服務端程式碼,與 Python SDK 程式碼。更多語言或框架,也是一樣操作的。
快速開始
先熟悉下工具,直接用官方 Docker 映象生成 Petstore 樣例的 Go SDK 程式碼:
docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate \
-i https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/3_0/petstore.yaml \
-g go \
-o /local/out/go
生成程式碼在當前目錄的 ./out/go
。
開啟 Swagger Editor File > Import URL
檢視 petstore.yaml
API:
檢視 openapi-generator-cli
用法:
docker run --rm -it \
-v "${PWD}:/local" \
--entrypoint /bin/bash \
openapitools/openapi-generator-cli
ln -s /usr/local/bin/docker-entrypoint.sh /usr/local/bin/openapi-generator
openapi-generator help
openapi-generator help generate
動手實踐
設計 RESTful API
開啟 Swagger Editor 設計 API:
/albums
- GET - Get all albums
- POST - Create a new album
/albums/:id
- GET - Get an album by its id
- PUT - Update an album by its id
- DELETE - Delete an album by its id
完整 API 描述檔案見 spec/api.yaml,主要包含三部分:
1 頭部: API 資訊
openapi: 3.0.0
info:
title: Start OpenAPITools
description: Let's practice designing our api.
version: 0.1.0
license:
name: MIT
url: https://spdx.org/licenses/MIT.html
servers:
- url: https://github.com/ikuokuo/start-openapitools
2 中間: paths
及其操作 (get
, post
, etc.)
paths:
/albums/{id}:
get:
tags:
- album
summary: Get an album by its id
operationId: getAlbum
parameters:
- $ref: '#/components/parameters/AlbumId'
responses:
200:
description: Get success, return the album
content:
application/json:
schema:
$ref: '#/components/schemas/Album'
404:
description: Album not found
3 底部: 可重用的 components
,於文件裡 $ref
引用
components:
parameters:
AlbumId:
name: id
in: path
description: Album id
required: true
schema:
type: string
schemas:
Album:
title: Album
type: object
required:
- title
- artist
- price
properties:
id:
type: string
format: uuid
title:
type: string
maxLength: 200
minLength: 1
artist:
type: string
maxLength: 100
minLength: 1
price:
type: number
format: double
minimum: 0.0
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
具體說明,請閱讀 OpenAPI Specification。
線上生成程式碼
可以用線上服務快速生成程式碼:
- latest stable version: https://api.openapi-generator...
以下則是自己動手生成的過程。
生成 Server Stub 程式碼
生成 Go Gin 樁(Stub)程式碼:
docker run --rm -it \
-v "${PWD}:/local" \
--entrypoint /bin/bash \
openapitools/openapi-generator-cli
ln -s /usr/local/bin/docker-entrypoint.sh /usr/local/bin/openapi-generator
# Config Options for go-gin-server
# https://openapi-generator.tech/docs/generators/go-gin-server
openapi-generator config-help -g go-gin-server
openapi-generator generate \
-g go-gin-server \
-i /local/spec/swagger.yaml \
-o /local/out/gin-server \
--additional-properties=packageName=startapi
生成內容:
❯ tree out/gin-server -aF --dirsfirst
out/gin-server
├── .openapi-generator/
├── api/
│ └── openapi.yaml
├── go/
│ ├── README.md
│ ├── api_album.go
│ ├── api_albums.go
│ ├── model_album.go
│ └── routers.go
├── .openapi-generator-ignore
├── Dockerfile
└── main.go
簡單實現 GetAlbum
介面,位於 go/api_album.go
:
// GetAlbum - Get an album by its id
func GetAlbum(c *gin.Context) {
c.JSON(http.StatusOK, Album{
Id: "3fa85f64-5717-4562-b3fc-2c963f66afa6",
Title: "Start OpenAPITools",
Artist: "GoCoding",
Price: 0.99,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
})
}
執行服務:
cd out/gin-server/
# 初始化模組
go mod init github.com/ikuokuo/start-openapitools/gin-server
go mod tidy
# 修改 `main.go` 中的 import 路徑
# sw "github.com/ikuokuo/start-openapitools/gin-server/go"
# 替換成本地路徑
go mod edit -replace github.com/ikuokuo/start-openapitools/gin-server/go=./go
執行結果:
❯ go run .
2021/11/05 18:20:00 Server started
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /ikuokuo/start-openapitools/ --> github.com/ikuokuo/start-openapitools/gin-server/go.Index (3 handlers)
[GIN-debug] DELETE /ikuokuo/start-openapitools/albums/:id --> github.com/ikuokuo/start-openapitools/gin-server/go.DeleteAlbum (3 handlers)
[GIN-debug] GET /ikuokuo/start-openapitools/albums/:id --> github.com/ikuokuo/start-openapitools/gin-server/go.GetAlbum (3 handlers)
[GIN-debug] PUT /ikuokuo/start-openapitools/albums/:id --> github.com/ikuokuo/start-openapitools/gin-server/go.PutAlbum (3 handlers)
[GIN-debug] GET /ikuokuo/start-openapitools/albums --> github.com/ikuokuo/start-openapitools/gin-server/go.GetAlbums (3 handlers)
[GIN-debug] POST /ikuokuo/start-openapitools/albums --> github.com/ikuokuo/start-openapitools/gin-server/go.PostAlbums (3 handlers)
[GIN-debug] Listening and serving HTTP on :8080
❯ curl http://localhost:8080/ikuokuo/start-openapitools/
Hello World!
生成 Client SDK 程式碼
生成 Python SDK 程式碼:
docker run --rm -it \
-v "${PWD}:/local" \
--entrypoint /bin/bash \
openapitools/openapi-generator-cli
ln -s /usr/local/bin/docker-entrypoint.sh /usr/local/bin/openapi-generator
# Config Options for python
# https://openapi-generator.tech/docs/generators/python
openapi-generator config-help -g python
openapi-generator generate \
-g python \
-i /local/spec/swagger.yaml \
-o /local/out/py-sdk \
--additional-properties=packageName=startapi \
--additional-properties=library=urllib3
生成內容:
❯ tree out/py-sdk -aF --dirsfirst
out/py-sdk
├── .openapi-generator/
├── docs/
├── startapi/
│ ├── api/
│ │ ├── __init__.py
│ │ ├── album_api.py
│ │ └── albums_api.py
│ ├── apis/
│ │ └── __init__.py
│ ├── model/
│ │ ├── __init__.py
│ │ └── album.py
│ ├── models/
│ │ └── __init__.py
│ ├── __init__.py
│ ├── api_client.py
│ ├── configuration.py
│ ├── exceptions.py
│ ├── model_utils.py
│ └── rest.py
├── test/
├── .gitignore
├── .gitlab-ci.yml
├── .openapi-generator-ignore
├── .travis.yml
├── README.md
├── git_push.sh
├── requirements.txt
├── setup.cfg
├── setup.py
├── test-requirements.txt
└── tox.ini
測試 SDK 使用,呼叫此前實現的 GetAlbum
介面:
❯ cd out/py-sdk/
❯ python - <<EOF
from startapi import ApiClient, Configuration, apis
config = Configuration(host="http://localhost:8080/ikuokuo/start-openapitools")
with ApiClient(configuration=config) as client:
api = apis.AlbumApi(client)
album = api.get_album("xxxxx")
print(album)
EOF
{'artist': 'GoCoding',
'created_at': datetime.datetime(2021, 11, 5, 18, 30, 0, 545305, tzinfo=tzoffset(None, 28800)),
'id': '3fa85f64-5717-4562-b3fc-2c963f66afa6',
'price': 0.99,
'title': 'Start OpenAPITools',
'updated_at': datetime.datetime(2021, 11, 5, 18, 30, 0, 545305, tzinfo=tzoffset(None, 28800))}
最後
實踐下來,感覺不錯。很多場合,生成 SDK 就夠用了。另外,生成自動化測試程式碼,也值得一試。
GoCoding 個人實踐的經驗分享,可關注公眾號!