OpenAPITools 实践

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:
OpenAPITools 实践
文章图片

查看 openapi-generator-cli 用法:
docker run --rm -it \ -v "${PWD}:/local" \ --entrypoint /bin/bash \ openapitools/openapi-generator-cliln -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-cliln -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-serveropenapi-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-cliln -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 pythonopenapi-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 - <

最后 【OpenAPITools 实践】实践下来,感觉不错。很多场合,生成 SDK 就够用了。另外,生成自动化测试代码,也值得一试。
GoCoding 个人实践的经验分享,可关注公众号!

    推荐阅读