Skip to content

Add support for opting out of streaming HTTP bodies #68

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Apr 2, 2025
22 changes: 22 additions & 0 deletions Sources/OpenAPIURLSession/URLSessionTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,32 @@ public struct URLSessionTransport: ClientTransport {
/// The URLSession used for performing HTTP operations.
public var session: URLSession

/// Creates a new configuration with the provided session.
/// - Parameters:
/// - session: The URLSession used for performing HTTP operations.
/// If none is provided, the system uses the shared URLSession.
/// - httpBodyProcessingMode: The mode used to process HTTP request and response bodies.
public init(session: URLSession = .shared, httpBodyProcessingMode: HTTPBodyProcessingMode = .platformDefault) {
let implementation = httpBodyProcessingMode.implementation
self.init(session: session, implementation: implementation)
}
/// Creates a new configuration with the provided session.
/// - Parameter session: The URLSession used for performing HTTP operations.
/// If none is provided, the system uses the shared URLSession.
public init(session: URLSession = .shared) { self.init(session: session, implementation: .platformDefault) }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding new parameters to existing functions is an API break, as caught by CI.

1 breaking change detected in OpenAPIURLSession:
  💔 API breakage: constructor URLSessionTransport.Configuration.init(session:) has been removed

We'd need to preserve this symbol that calls through to the new one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand the issue.

The new API provides public init(session: URLSession = .shared, httpBodyProcessingMode: HTTPBodyProcessingMode = .platformDefault) - and as there is a default parameter for httpBodyProcessingMode, doesn't Swift auto generate a public init(session: URLSession) for us?

The following code in my app compiles fine:

    func testFunction() async throws {
        
        let sessionConfiguration = URLSessionConfiguration.default
        let otherSession = URLSession(configuration: sessionConfiguration)
        
        let transportConfiguration = URLSessionTransport.Configuration.init(session: .shared)
        let otherTransportConfiguration = URLSessionTransport.Configuration.init(session: otherSession)
        
        
        let transport1 = URLSessionTransport(configuration: transportConfiguration)
        let transport2 = URLSessionTransport(configuration: otherTransportConfiguration)
        
        let client1 = Client(serverURL: URL(string: "https://example.com")!, transport: transport1)
        let client2 = Client(serverURL: URL(string: "https://example.com")!, transport: transport2)
        
        _ = try await client1.get_sol_Appversions_sol_All()
        _ = try await client2.get_sol_Appversions_sol_All()
    }

So to me, there still is an (implicit) URLSessionTransport.Configuration.init(session:) - isn't this API breakage error a false positive?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a false positive. It's possible to refer to the function itself (e.g. let initializer = URLSessionTransport.Configuration.init(session:)) which won't work if the function is no longer present.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation. Interesting, I wasn't aware of this limitation of default parameter values. I have added back the old single parameter init.

/// Specifies the mode in which HTTP request and response bodies are processed.
public struct HTTPBodyProcessingMode: Sendable {
/// Exposing the internal implementation directly.
fileprivate let implementation: Configuration.Implementation

private init(_ implementation: Configuration.Implementation) { self.implementation = implementation }

/// Use this mode to force URLSessionTransport to transfer data in a buffered mode, even if
/// streaming would be available on the platform.
public static let buffered = HTTPBodyProcessingMode(.buffering)
/// Data is transfered via streaming if available on the platform, else it falls back to buffering.
public static let platformDefault = HTTPBodyProcessingMode(.platformDefault)
}

enum Implementation {
case buffering
Expand Down