Skip to content

[RFC] ConnectionPool rewrite and http/2 support #376

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

Closed
wants to merge 10 commits into from
Closed
5 changes: 3 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ let package = Package(
.library(name: "AsyncHTTPClient", targets: ["AsyncHTTPClient"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-nio.git", from: "2.27.0"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.29.0"),
.package(url: "https://github.com/apple/swift-nio-http2.git", from: "1.7.0"),
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.13.0"),
.package(url: "https://github.com/apple/swift-nio-extras.git", from: "1.3.0"),
.package(url: "https://github.com/apple/swift-nio-transport-services.git", from: "1.5.1"),
Expand All @@ -30,7 +31,7 @@ let package = Package(
targets: [
.target(
name: "AsyncHTTPClient",
dependencies: ["NIO", "NIOHTTP1", "NIOSSL", "NIOConcurrencyHelpers", "NIOHTTPCompression",
dependencies: ["NIO", "NIOHTTP1", "NIOHTTP2", "NIOSSL", "NIOConcurrencyHelpers", "NIOHTTPCompression",
"NIOFoundationCompat", "NIOTransportServices", "Logging"]
),
.testTarget(
Expand Down
38 changes: 32 additions & 6 deletions Sources/AsyncHTTPClient/ConnectionPool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ final class ConnectionPool {
let provider = HTTP1ConnectionProvider(key: key,
eventLoop: taskEventLoop,
configuration: key.config(overriding: self.configuration),
tlsConfiguration: request.tlsConfiguration,
pool: self,
sslContextCache: self.sslContextCache,
backgroundActivityLogger: self.backgroundActivityLogger)
let enqueued = provider.enqueue()
assert(enqueued)
Expand Down Expand Up @@ -213,6 +215,8 @@ class HTTP1ConnectionProvider {

private let backgroundActivityLogger: Logger

private let factory: HTTPConnectionPool.ConnectionFactory

/// Creates a new `HTTP1ConnectionProvider`
///
/// - parameters:
Expand All @@ -225,7 +229,9 @@ class HTTP1ConnectionProvider {
init(key: ConnectionPool.Key,
eventLoop: EventLoop,
configuration: HTTPClient.Configuration,
tlsConfiguration: TLSConfiguration?,
pool: ConnectionPool,
sslContextCache: SSLContextCache,
backgroundActivityLogger: Logger) {
self.eventLoop = eventLoop
self.configuration = configuration
Expand All @@ -234,6 +240,13 @@ class HTTP1ConnectionProvider {
self.closePromise = eventLoop.makePromise()
self.state = .init(eventLoop: eventLoop)
self.backgroundActivityLogger = backgroundActivityLogger

self.factory = HTTPConnectionPool.ConnectionFactory(
key: self.key,
tlsConfiguration: tlsConfiguration ?? configuration.tlsConfiguration ?? .forClient(),
clientConfiguration: self.configuration,
sslContextCache: sslContextCache
)
}

deinit {
Expand Down Expand Up @@ -440,12 +453,25 @@ class HTTP1ConnectionProvider {

private func makeChannel(preference: HTTPClient.EventLoopPreference,
logger: Logger) -> EventLoopFuture<Channel> {
return NIOClientTCPBootstrap.makeHTTP1Channel(destination: self.key,
eventLoop: self.eventLoop,
configuration: self.configuration,
sslContextCache: self.pool.sslContextCache,
preference: preference,
logger: logger)
let connectionID = HTTPConnectionPool.Connection.ID.globalGenerator.next()
let eventLoop = preference.bestEventLoop ?? self.eventLoop
return self.factory.makeBestChannel(connectionID: connectionID, eventLoop: eventLoop, logger: logger).flatMapThrowing {
(channel, _) -> Channel in

// add the http1.1 channel handlers
let syncOperations = channel.pipeline.syncOperations
try syncOperations.addHTTPClientHandlers(leftOverBytesStrategy: .forwardBytes)

switch self.configuration.decompression {
case .disabled:
()
case .enabled(let limit):
let decompressHandler = NIOHTTPResponseDecompressor(limit: limit)
try syncOperations.addHandler(decompressHandler)
}

return channel
}
}

/// A `Waiter` represents a request that waits for a connection when none is
Expand Down
Loading