隆重推出 Swift OpenAPI Generator

我们很高兴地宣布推出一套开源库,旨在帮助客户端和服务器开发者简化围绕使用行业标准 OpenAPI 规范进行 HTTP 通信的工作流程。

什么是 OpenAPI?

OpenAPI 是一种用于记录 HTTP 服务的规范。OpenAPI 文档以 YAML 或 JSON 编写,可以被工具读取,以帮助自动化工作流程,例如生成发送和接收 HTTP 请求所需的代码。

通过作为事实来源,OpenAPI 解决了服务及其客户端之间 API 契约的沟通问题。它消除了阅读可能不准确的手写文档或观察网络流量的需求,仅仅是为了弄清楚调用服务的正确方法。它可以帮助您避免这种耗时、重复且容易出错的工作——不仅在首次采用服务时,而且在服务不断发展时也是如此。

为了了解 OpenAPI 及其优势的实际应用,让我们考虑一个名为 GreetingService 的简单服务,该服务:

{
  "message" : "Hello, Jane!"
}

可以使用以下 OpenAPI 文档描述这样的服务:

openapi: '3.0.3'
info:
  title: GreetingService
  version: 1.0.0
servers:
  - url: "https://127.0.0.1:8080"
    description: "Localhost"
paths:
  /greet:
    get:
      operationId: getGreeting
      parameters:
        - name: name
          in: query
          schema:
            type: string
      responses:
        '200':
          description: A success response with a greeting.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Greeting"
components:
  schemas:
    Greeting:
      properties:
        message:
          type: string
      required:
        - message

这个简单的 OpenAPI 文档定义了 HTTP 请求和响应的结构,包括 HTTP 方法、URL 路径和查询参数、HTTP 状态代码和内容类型,并使用 JSON Schema 来描述响应正文的结构。

OpenAPI 还允许定义上面未显示的其他详细信息,例如查询项和请求正文(有关更多详细信息,请参阅 OpenAPI 3.0.3 规范)。

Swift OpenAPI Generator

Swift OpenAPI Generator 是一个 SwiftPM 插件,它接受 OpenAPI 文档,并生成用于执行 HTTP 调用的客户端代码或用于处理这些调用的服务器代码。生成的代码在每项操作的类型安全输入和输出表示与底层 HTTP 请求和响应之间进行转换。

因此,无论是开发充当 GreetingService 客户端的应用,还是实现 GreetingService 本身,Swift OpenAPI Generator 都会为您生成网络代码,使您可以专注于核心逻辑。

采用插件

要使用 Swift OpenAPI Generator 插件,您需要:

  1. 为以下项添加软件包依赖项:
    • 软件包插件 (swift-openapi-generator),它在构建时执行代码生成
    • 运行时库 (swift-openapi-runtime),其中包含生成的代码和扩展库使用的协议定义
    • 传输实现,允许插入您选择的 HTTP 客户端库或服务器框架
  2. 在您的目标上启用软件包插件,并为运行时和传输库添加目标依赖项。
  3. 将以下两个文件添加到您的目标:
    • openapi.yaml,描述您的 API 的 OpenAPI 文档。
    • openapi-generator-config.yaml,插件的配置文件,用于控制是生成客户端代码还是服务器代码。

提示:有关在您的 Swift 软件包或 Xcode 项目中采用插件的更多信息,请查看我们的逐步教程

使用生成的 API 客户端

在开发客户端(例如 iOS 应用)时,您将获得两种生成的类型:

以下是实例化客户端并从服务器获取问候语的示例代码:

import OpenAPIRuntime
import OpenAPIURLSession

// Instantiate your chosen transport library.
let transport: ClientTransport = URLSessionTransport()

// Create a client to connect to a server URL documented in the OpenAPI document.
let client = Client(
    serverURL: try Servers.server1(),
    transport: transport
)

// Make the HTTP call using a type-safe method.
let response = try await client.getGreeting(.init(query: .init(name: "Jane")))

// Switch over the HTTP response status code.
switch response {
case .ok(let okResponse):
    // Switch over the response content type.
    switch okResponse.body {
    case .json(let greeting):
        // Print the greeting message.
        print("👋 \(greeting.message)")
    }
case .undocumented(statusCode: let statusCode, _):
    // Handle HTTP response status codes not documented in the OpenAPI document.
    print("🥺 undocumented response: \(statusCode)")
}

注意:虽然上面的示例代码使用了基于 URLSession 的客户端传输,但还有其他客户端传输实现,或者您可以创建自己的实现。

使用生成的 API 服务器存根

在开发服务器时,您将获得两种生成的类型,可在您的代码中使用:

以下是实现简单处理程序并使用它启动服务器的示例代码:

import OpenAPIRuntime
import OpenAPIVapor
import Vapor

// A server implementation of the GreetingService API.
struct Handler: APIProtocol {

    func getGreeting(
        _ input: Operations.getGreeting.Input
    ) async throws -> Operations.getGreeting.Output {
        let message = "Hello, \(input.query.name ?? "Stranger")!"
        let greeting = Components.Schemas.Greeting(message: message)
        return .ok(.init(body: .json(greeting)))
    }
}

// Create the Vapor app.
let app = Vapor.Application()

// Create the transport.
let transport: ServerTransport = VaporTransport(routesBuilder: app)

// Create the request handler, which contains your server logic.
let handler = Handler()

// Register the generated routes on the transport.
try handler.registerHandlers(on: transport)

// Start the server.
try app.run()

注意:虽然上面的示例代码使用了基于 Vapor 的服务器传输,但还有其他服务器传输实现,或者您可以创建自己的实现。

传输实现

Swift OpenAPI Generator 通过在协议 ClientTransportServerTransport 中抽象 HTTP 库接口,从而可以与任何 HTTP 客户端或服务器库一起使用。与 swift-log 等项目类似,Swift OpenAPI Generator 使用API 软件包方法来实现更大的可扩展性。

以下是一些现有传输实现的示例,您可以立即试用:

客户端传输实现

服务器传输实现

下一步是什么

该项目在其开发的早期阶段开源,以便社区可以提供反馈并帮助我们达成稳定的 1.0 版本。

最初的重点是实现 OpenAPI 规范 3.0.3 版本 定义的功能,目前正在进行支持 OpenAPI 3.1 的工作。

虽然 Swift OpenAPI Generator 支持 OpenAPI 的大多数常用功能,但仍有多个功能需要实现,并且使用 GitHub 问题跟踪公开跟踪进度。

参与进来

查看存储库、未解决的问题、拉取请求,并在 Swift 论坛中告诉我们您的想法。

我们对 Swift OpenAPI Generator 可以为 Swift 社区做些什么感到兴奋,它可以减少连接到 HTTP 服务或自己实现服务所需的时间。