Swift OpenAPI Generator 0.3.0 Released (Swift HTTP Types, streaming bodies, shorthand APIs)

We’re happy to announce that Swift OpenAPI Generator 0.3.0 was just released!

Since it went open source in May 2023 with version 0.1.0, Swift OpenAPI Generator merged almost 150 pull requests, released 17 patch updates, and introduced support for several new features.

It wouldn’t be possible without over a dozen new contributors who filed great issues, dove into the code and opened pull requests, provided feedback on proposals, and helped prioritize which issues need to get addressed first based on real-world usage.

Since the last release, Swift OpenAPI Generator has also been accepted into the Swift Server Working Group.

Highlights

In addition to several bug fixes, here are a few notable changes in this release:

New features

  • Support streaming request and response bodies (#254)
    • This feature unlocks use cases where large files can be uploaded and downloading without buffering, or where the response body represents a live stream of events, allowing the creating of a publish/subscribe system.
    • The URLSession, AsyncHTTPClient, Vapor, and Hummingbird transports have all been updated to use the new API, and most are now fully streaming.
  • Transport and middleware APIs defined in terms of the new, ecosystem-wide, Swift HTTP Types (#254)
    • This removes the need for Swift OpenAPI Runtime to define its own types and, for libraries that work with Swift HTTP Types, removes the need for conversion.
  • Shorthand APIs for providing inputs and handling outputs (#308)
    • Simplified API for adopters who do not want to match against all documented and undocumented outcomes, further reducing ceremony, especially for operations with a single documented successful outcome.
    • Generates throwing getters for each enum case for response statuses and response body content.
    • Generate overloads with input parameters as operation parameters.
    • // before
      switch try await client.getGreeting(.init()) {
      case .ok(let response):
          switch response.body {
          case .json(let body):
              print(body.message)
          }
      case .undocumented(statusCode: _, _):
          throw UnexpectedResponseError()
      }
      
      // after
      print(try await client.getGreeting().ok.body.json.message)
      //                                ^  ^       ^
      //                                |  |       `- Throws if body did not deserialize as documented JSON.
      //                                |  |
      //                                |  `- Throws if HTTP response is not 200 (OK).
      //                                |
      //                                `- No need to wrap parameters in input value.
      
  • More OpenAPI specification coverage
    • URL-encoded request bodies
    • Integer-backed enums
    • Nullable schemas

Other improvements

  • Add compatibility suite with selected OpenAPI documents (#267)
    • In order to help shape the 1.0 release, we've created a public compatibility test suite, with some selected real-world OpenAPI documents.

Accepted proposals

Breaking changes

:warning: This release also contains a few breaking changes that allow the project to apply feedback on the API that would be difficult to add in a backwards compatible way. This is part of our strategy to reach version 1.0 in the coming months. See the next section for details on how to update your code.

Migrating from 0.2.x to 0.3.0

The 0.3.0 tags are now ready on the generator and runtime repositories, as well as on the URLSession, AsyncHTTPClient, Vapor, and Hummingbird transports.

This makes upgrading to 0.3.0 as easy as changing all of your Swift OpenAPI package dependencies:

- .package(url: "https://github.com/apple/swift-openapi-...", .upToNextMinor(from: "0.2.0")),
+ .package(url: "https://github.com/apple/swift-openapi-...", .upToNextMinor(from: "0.3.0")),

Due to the presence of some API-breaking changes, after you rebuild, you might encounter build errors.

Below are some of the errors you might see and how to resolve them.

  • Change: all feature flags from 0.2.x have been enabled by default, and flags removed
    • Error: unknown feature flags
    • Fix: do not pass the feature flags anymore, they are all enabled by default in 0.3.0 and the legacy behaviors have been removed
  • Change: Swift HTTP types
    • Error: you are relying on binary response body being Foundation.Data or Swift.String
    • Fix: Use Data(collecting:upTo:) or String(collecting:upTo:), respectively, or start consuming the body in chunks using for try await chunk in body { ... }.
  • Change: Swift HTTP types
    • Error: Unknown type Request / Response in middleware or transport implementation.
    • Error: type does not conform to transport or middleware protocol
    • Fix: Update to the new middleware or transport APIs. If you want a quick compatibility fix, you can buffer the entire body in memory using Data(collecting: body, upTo: .max) while you work on migrating to an async implementation.

What’s next

With 0.3.0 out the door, we continue working towards 1.0. In the meantime, we expect to make patch releases to broaden our support for the OpenAPI specification and to make it easier to work with larger APIs, with document filtering.

Thanks again to all our contributors and if you’d like to get involved, check out Swift OpenAPI Generator on GitHub.

13 Likes