-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
221 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the Swift OpenFeature open source project | ||
// | ||
// Copyright (c) 2025 the Swift OpenFeature project authors | ||
// Licensed under Apache License v2.0 | ||
// | ||
// See LICENSE.txt for license information | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import AsyncHTTPClient | ||
import Foundation | ||
import HTTPTypes | ||
import Logging | ||
import NIOCore | ||
import OpenAPIAsyncHTTPClient | ||
import OpenAPIRuntime | ||
|
||
struct OFREPHTTPClientTransport: OFREPClientTransport { | ||
let transport: AsyncHTTPClientTransport | ||
let shouldShutDownHTTPClient: Bool | ||
|
||
func send( | ||
_ request: HTTPRequest, | ||
body: HTTPBody?, | ||
baseURL: URL, | ||
operationID: String | ||
) async throws -> ( | ||
HTTPResponse, | ||
HTTPBody? | ||
) { | ||
try await transport.send(request, body: body, baseURL: baseURL, operationID: operationID) | ||
} | ||
|
||
func shutdownGracefully() async throws { | ||
guard shouldShutDownHTTPClient else { return } | ||
try await transport.configuration.client.shutdown() | ||
} | ||
|
||
static let loggingDisabled = Logger(label: "OFREP-do-not-log", factory: { _ in SwiftLogNoOpLogHandler() }) | ||
} | ||
|
||
extension OFREPProvider<OFREPHTTPClientTransport> { | ||
public init(serverURL: URL, httpClient: HTTPClient = .shared, timeout: Duration = .seconds(60)) { | ||
self.init( | ||
serverURL: serverURL, | ||
transport: AsyncHTTPClientTransport( | ||
configuration: AsyncHTTPClientTransport.Configuration( | ||
client: httpClient, | ||
timeout: TimeAmount(timeout) | ||
) | ||
) | ||
) | ||
} | ||
|
||
public init( | ||
serverURL: URL, | ||
configuration: HTTPClient.Configuration, | ||
eventLoopGroup: EventLoopGroup = HTTPClient.defaultEventLoopGroup, | ||
backgroundActivityLogger: Logger? = nil, | ||
timeout: Duration = .seconds(60) | ||
) { | ||
let httpClient = HTTPClient( | ||
eventLoopGroupProvider: .shared(eventLoopGroup), | ||
configuration: configuration, | ||
backgroundActivityLogger: backgroundActivityLogger ?? OFREPHTTPClientTransport.loggingDisabled | ||
) | ||
let httpClientTransport = AsyncHTTPClientTransport( | ||
configuration: AsyncHTTPClientTransport.Configuration( | ||
client: httpClient, | ||
timeout: TimeAmount(timeout) | ||
) | ||
) | ||
self.init( | ||
serverURL: serverURL, | ||
transport: OFREPHTTPClientTransport(transport: httpClientTransport, shouldShutDownHTTPClient: true) | ||
) | ||
} | ||
|
||
package init(serverURL: URL, transport: AsyncHTTPClientTransport) { | ||
self.init( | ||
serverURL: serverURL, | ||
transport: OFREPHTTPClientTransport(transport: transport, shouldShutDownHTTPClient: false) | ||
) | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
Tests/OFREPTests/Helpers/ServiceGroup+ShutdownTrigger.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the Swift OpenFeature open source project | ||
// | ||
// Copyright (c) 2025 the Swift OpenFeature project authors | ||
// Licensed under Apache License v2.0 | ||
// | ||
// See LICENSE.txt for license information | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import ServiceLifecycle | ||
|
||
private struct ShutdownTriggerService: Service, CustomStringConvertible { | ||
let description = "ShutdownTrigger" | ||
|
||
func run() async throws {} | ||
} | ||
|
||
extension ServiceGroupConfiguration.ServiceConfiguration { | ||
/// A no-op service which is used to shut down the service group upon successful termination. | ||
static let shutdownTrigger = Self( | ||
service: ShutdownTriggerService(), | ||
successTerminationBehavior: .gracefullyShutdownGroup | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the Swift OpenFeature open source project | ||
// | ||
// Copyright (c) 2025 the Swift OpenFeature project authors | ||
// Licensed under Apache License v2.0 | ||
// | ||
// See LICENSE.txt for license information | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import Foundation | ||
|
||
extension URL { | ||
static let stub = URL(string: "http://stub.stub")! | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the Swift OpenFeature open source project | ||
// | ||
// Copyright (c) 2025 the Swift OpenFeature project authors | ||
// Licensed under Apache License v2.0 | ||
// | ||
// See LICENSE.txt for license information | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import AsyncHTTPClient | ||
import Foundation | ||
import Logging | ||
import NIOCore | ||
import OFREP | ||
import ServiceLifecycle | ||
import Testing | ||
|
||
@testable import OpenAPIAsyncHTTPClient | ||
|
||
@Suite("HTTP Client Transport") | ||
struct OFREPHTTPClientTransportTests { | ||
@Test("Defaults to shared HTTP client") | ||
func sharedHTTPClient() async throws { | ||
let provider = OFREPProvider(serverURL: .stub) | ||
|
||
let serviceGroup = ServiceGroup( | ||
configuration: .init( | ||
services: [.init(service: provider), .shutdownTrigger], | ||
logger: Logger(label: "test") | ||
) | ||
) | ||
|
||
try await serviceGroup.run() | ||
} | ||
|
||
@Test("Shuts down internally created HTTP client") | ||
func internallyCreatedHTTPClient() async throws { | ||
let provider = OFREPProvider(serverURL: .stub, configuration: HTTPClient.Configuration()) | ||
|
||
let serviceGroup = ServiceGroup( | ||
configuration: .init( | ||
services: [.init(service: provider), .shutdownTrigger], | ||
logger: Logger(label: "test") | ||
) | ||
) | ||
|
||
try await serviceGroup.run() | ||
} | ||
|
||
@Test("Forwards request to AsyncHTTPClientTransport") | ||
func forwardsRequest() async throws { | ||
let requestSender = RecordingRequestSender() | ||
let transport = AsyncHTTPClientTransport(configuration: .init(), requestSender: requestSender) | ||
let provider = OFREPProvider(serverURL: .stub, transport: transport) | ||
|
||
_ = await provider.resolution(of: "flag", defaultValue: false, context: nil) | ||
|
||
await #expect(requestSender.requests.count == 1) | ||
} | ||
} | ||
|
||
private actor RecordingRequestSender: HTTPRequestSending { | ||
var requests = [Request]() | ||
|
||
func send( | ||
request: HTTPClientRequest, | ||
with client: HTTPClient, | ||
timeout: TimeAmount | ||
) async throws -> AsyncHTTPClientTransport.Response { | ||
requests.append(Request(request: request, client: client, timeout: timeout)) | ||
return HTTPClientResponse() | ||
} | ||
|
||
struct Request { | ||
let request: HTTPClientRequest | ||
let client: HTTPClient | ||
let timeout: TimeAmount | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters