使用OpenAPI生成API客户端代码 - Phrase

作者:API传播员 · 2025-11-21 · 阅读时间:4分钟

我们已经开发了 Ruby 和 Go 的客户端库,但为了让 API 更加易用,我们希望支持更多的编程语言。然而,手动开发和维护这些库不仅耗时,而且随着支持语言的增加,工作量也会成倍增长。为了应对这些挑战,我们决定采用 OpenAPI 规范(OAS)来描述 API,并通过 OpenAPI 生成器自动生成多种编程语言的客户端库。

OpenAPI 规范是一种标准化的方式,用于描述 REST API 的功能,使得人类和计算机都能轻松发现和理解服务的功能。


使用 OpenAPI 描述 API

使用 OpenAPI 描述 API 的过程相对简单。您可以将所有内容集中在一个文件中,但将其逻辑拆分会更易于管理。例如:

openapi: 3.0.3

info:
  title: Phrase API Reference
  version: 2.0.0
  description:
    $ref: './intro.md'
  termsOfService: 'https://phrase.com/legal/'
  license:
    name: MIT
    url: https://choosealicense.com/licenses/mit/

servers:
  - url: https://api.phrase.com/v2

security:
  - Token: []
  - Basic: []

components:
  securitySchemes:
    Token:
      type: apiKey
      in: header
      name: Authorization
      description: Enter your token in the format **token TOKEN**
    Basic:
      type: http
      scheme: basic
  headers:
    $ref: "./headers.yaml"
  schemas:
    $ref: "./schemas.yaml#/schemas"
  parameters:
    $ref: "./parameters.yaml"
  responses:
    $ref: "./responses.yaml"

paths:
  $ref: "./paths.yaml"

结构说明

  • info:包含所有人类可读的信息。
  • servers:定义了多个服务器地址,例如生产环境和测试环境。
  • security:列出了所有授权方法。
  • components:定义了可重用的组件,例如 headers 和 responses。
  • paths:描述了 API 的具体端点。

通过 $ref 关键字,可以将文档拆分为多个部分甚至多个文件,从而提高可维护性。例如:

"/projects":
  get:
    "$ref": "./paths/projects/index.yaml"
  post:
    "$ref": "./paths/projects/create.yaml"

"/projects/{id}":
  get:
    "$ref": "./paths/projects/show.yaml"
  patch:
    "$ref": "./paths/projects/update.yaml"
  delete:
    "$ref": "./paths/projects/destroy.yaml"

这种拆分方式不仅提高了文档的可读性,还能重用部分内容,例如项目列表的定义。


开始生成代码

在生成代码之前,我们需要将所有拆分的文件合并为一个文件,因为 OpenAPI Generator 要求所有定义集中在一个文件中。为此,我们使用了 swagg-cli 工具进行合并。

完成合并后,我们可以使用 OpenAPI Generator 生成客户端库。以下是一些支持的语言示例:Ruby、Go 和 TypeScript。

需要注意的是,不同生成器的质量可能存在差异,有些生成的代码甚至可能存在问题。因此,在使用生成的代码之前,务必仔细检查其质量。


自动化生成和发布

生成代码只是第一步,将其自动化并公开发布同样重要。我们使用 GitHub Actions 实现了这一流程。当 OpenAPI 仓库发生变更时,GitHub Actions 会自动触发以下操作:

  1. 生成客户端库。
  2. 将生成的代码推送到单独的仓库。

以下是 GitHub Actions 的配置示例:

name: API Clients

on:
  push:
    branches:
      - master

jobs:
  build-go:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout 🛎️
        uses: actions/checkout@v2
        with:
          persist-credentials: false

      - name: Set up Go
        uses: actions/setup-go@v2
        with:
          go-version: 1.14

      - name: Build and Deploy 🚀
        env:
          API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          go get golang.org/x/tools/cmd/goimports
          npm install
          npm run generate.go
          git clone --depth 1 https://$API_TOKEN_GITHUB@github.com/phrase/phrase-go.git clones/go &> /dev/null
          rsync -a --delete --exclude='.git/' clients/go/ clones/go
          cd clones/go
          goimports -w .
          if [ -n "$(git status --porcelain)" ]; then
            git config --global user.email "support@phrase.com"
            git config --global user.name "Phrase"
            git add .
            git commit --message "Deploying from phrase/openapi@${GITHUB_SHA::8}"
            git push origin master
          else
            echo "No changes, skipping."
          fi

通过这种方式,任何变更都会自动生成并发布,确保客户端库始终保持最新。


结论

总体来说,使用 OpenAPI 生成 API 客户端代码的过程相当顺利,尽管也遇到了一些小问题。例如,不同工具对 OpenAPI v3 标准的支持不一致,部分工具还依赖供应商扩展。

然而,通过 OpenAPI,我们实现了一种一致且可重复的方式来生成多语言的 API 客户端库。这不仅简化了维护工作,还让所有内容都依赖于一个单一的事实来源,符合行业标准。

我们非常喜欢这种轻量级的工具链,它让生成和更新客户端库变得更加高效。

原文链接: https://phrase.com/blog/posts/using-openapi-to-generate-api-client-code/