Swift Digest
Blog | Swift.org Blog

Swift OpenAPI Generator 1.0 リリース

Swift OpenAPI Generator 1.0 Released

このダイジェストはClaude Opus 4.7 / 4.8によって生成されたものです(License)。原文はこちら

この記事の要点

何が発表されたのか

OpenAPI は、HTTP サービスの振る舞いを記述するためのオープンな標準で、豊富なツールのエコシステムを持ちます。インタラクティブなドキュメントの生成で知られていますが、本来の中心的な動機はコード生成です。これにより、サーバー開発では API ファーストのアプローチが取れ、クライアント開発では、すでに OpenAPI 形式で API を記述している多くの既存サービスに対して、型安全でidiomaticな呼び出しコードを生成できます。

現実の API は数百もの操作を持つことが多く、それぞれがリッチなリクエスト・レスポンスの型、ヘッダーフィールド、パラメータなどを伴います。これらのコードを操作ごとに手で書いて保守するのは、反復的で冗長になりがちで、間違いも起きやすい作業です。

Swift OpenAPI Generator は、API 呼び出しを行うコードや API サーバーを実装するコードを生成する SwiftPM プラグインです。コードはビルド時に自動生成されるため、OpenAPI ドキュメントと常に同期し、ソースリポジトリにコミットする必要がありません。

何に使えるのか

たとえば、名前を受け取ってパーソナライズされた挨拶を返す、次のような API エンドポイントを考えます。

% curl 'https://example.com/api/greet?name=Jane'
{
    "message": "Hello, Jane"
}

このサービスは、OpenAPI ドキュメント(openapi.yaml)で次のように記述できます。クエリパラメータ name を受け取り、200 レスポンスとして message を持つ JSON を返すことが定義されています。

openapi: '3.1.0'
info:
  title: GreetingService
  version: 1.0.0
servers:
  - url: https://example.com/api
    description: Example service deployment.
paths:
  /greet:
    get:
      operationId: getGreeting
      parameters:
        - name: name
          required: false
          in: query
          description: The name used in the returned greeting.
          schema:
            type: string
      responses:
        '200':
          description: A success response with a greeting.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Greeting'
components:
  schemas:
    Greeting:
      type: object
      description: A value with the greeting contents.
      properties:
        message:
          type: string
          description: The string representation of the greeting.
      required:
        - message

このドキュメントを入力に、クライアントコードとサーバーコードのどちらでも生成できます。

生成されたクライアント API

クライアントを生成すると、OpenAPI ドキュメントの操作ごとにメソッドを持つ Client 型が生成されます。Swift OpenAPI Generator 向けの統合パッケージを提供する任意の HTTP ライブラリと組み合わせられます。生成コードはビルドシステムが決める場所にビルド時に出力されるため、利用側はサーバー URL と使いたい HTTP の transport を渡して Client を作るだけです。

次の例は、内部の HTTP 通信に URLSession を使うクライアントを作成しています。

import OpenAPIURLSession
import Foundation

let client = Client(
    serverURL: URL(string: "http://localhost:8080/api")!,
    transport: URLSessionTransport()
)
let response = try await client.getGreeting()
print(try response.ok.body.json.message)

生成されたサーバースタブ

サーバーを生成すると、OpenAPI ドキュメントの操作ごとにメソッド要件を定義したプロトコル APIProtocol が生成されます。これは、Swift OpenAPI Generator 向けの統合パッケージを提供する任意の Web フレームワークと連携するよう設計されています。

API サーバーを実装するには、APIProtocol に適合する型を定義し、各操作の中心となるロジックだけを記述します。サーバーの起動時には、生成された registerHandlers 関数を使って、HTTP リクエストを自分のハンドラへルーティングするよう HTTP サーバーを設定します。

次の例は、Greeting Service API を Handler という型で実装し、HTTP リクエストを処理するよう Vapor の Web サーバーを設定しています。

import OpenAPIRuntime
import OpenAPIVapor
import Vapor

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

@main struct Server {
    static func main() async throws {
        let app = Vapor.Application()
        let transport = VaporTransport(routesBuilder: app)
        let handler = Handler()
        try handler.registerHandlers(on: transport, serverURL: URL(string: "/api")!)
        try await app.execute()
    }
}

パッケージのエコシステム

Swift OpenAPI Generator は、拡張性を高めプロジェクトの依存関係を最小限に抑えるため、複数のリポジトリに分割されています。

導入・今後の位置づけ

導入を始めるには、ドキュメントと、ステップバイステップのチュートリアルが用意されています。エコシステムの他のパッケージと連携するサンプルプロジェクトで試すこともできます。

質問・機能要望・バグ報告は、GitHub の各リポジトリを通じて受け付けられています。

関連リンク