Swift OpenAPI Generator 1.0 Released

Si Beaumont is a member of a team developing foundational server-side Swift libraries as part of Apple’s Services Engineering division, and is a core developer on Swift OpenAPI Generator.
Honza Dvorsky is a member of a team working on developer tools and services as part of Apple’s Services Engineering division, and is a core developer on Swift OpenAPI Generator.

We’re happy to announce the stable 1.0 release of Swift OpenAPI Generator!

OpenAPI is an open standard for describing the behavior of HTTP services with a rich ecosystem of tooling. One thing OpenAPI is particularly known for is tooling to generate interactive documentation. But the core motivation of OpenAPI is code-generation, which allows adopters to use an API-first approach to server development and, because many existing services document their API in this format, allows client developers to generate type-safe, idiomatic code to call these APIs.

Many real-world APIs have hundreds of operations, each with rich request and response types, header fields, parameters, and more. Writing and maintaining this code for every operation can be repetitive, verbose, and error-prone.

Swift OpenAPI Generator is a Swift package plugin that generates the code required to make API calls and implement API servers. The code is automatically generated at build-time, so it’s always in sync with the OpenAPI document and doesn’t need to be committed to your source repository.

Since the initial release six months ago, the project received over 250 pull requests, from more than 20 contributors, and has gained several new features and a simpler API.

Feature Highlights

A Quick Look

Consider a fictitious HTTP server that provides a single API endpoint to return a personalized greeting:

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

This service can be described using the following OpenAPI document:

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

Swift OpenAPI Generator can be configured to generate:

Generated Client API

The generated code provides a type, named Client, which provides a method for each operation defined in the OpenAPI document and can be used with any HTTP library that provides an integration package for Swift OpenAPI Generator.

The plugin produces the generated code at build time in a location determined by the build system. To use the generated code in your project, simply create a Client by providing the server URL and HTTP transport you’d like to use.

The following example creates a Greeting Service client that uses URLSession to make the underlying HTTP requests.

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)

Generated Server API Stubs

The generated code provides a Swift protocol, named APIProtocol, which defines a method requirement for each operation defined in the OpenAPI document, and is designed to work with any web framework that provides an integration package for Swift OpenAPI Generator.

To implement an API server, define a type that conforms to APIProtocol, providing just the business logic for each operation.

To start the API server, use the generated registerHandlers function to configure the HTTP server to route the HTTP requests to your handler.

The following example implements the Greeting Service API in a type named Handler and configures a Vapor web server to serve the HTTP requests.

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()
    }
}

Package Ecosystem

The Swift OpenAPI Generator project is split across multiple repositories to enable extensibility and minimize dependencies in your project.

Next Steps

To get started, check out the documentation, which contains step-by-step tutorials.

You can also experiment with example projects that use Swift OpenAPI Generator and integrate with other packages in the ecosystem.

Or if you prefer to watch a video, check out Meet Swift OpenAPI Generator from WWDC23.

To ask a question, request a feature, or report a bug, reach out to us on Github 👋.