@@ -29,21 +29,20 @@ extension HTTPConnectionPool {
29
29
}
30
30
31
31
final class ConnectionFactory {
32
-
33
32
struct Timeouts {
34
33
/// the `TimeAmount` waited before the TCP connection creation is failed with a timeout error
35
34
var connect : TimeAmount = . seconds( 10 )
36
-
35
+
37
36
/// the `TimeAmount` waited before the SOCKS proxy connection creation is failed with a timeout error
38
37
var socksProxyHandshake : TimeAmount = . seconds( 10 )
39
-
38
+
40
39
/// the `TimeAmount` waited before the HTTP proxy connection creation is failed with a timeout error
41
40
var httpProxyHandshake : TimeAmount = . seconds( 10 )
42
-
41
+
43
42
/// the `TimeAmount` waited before we the TLS handshake is failed with a timeout error
44
43
var tlsHandshake : TimeAmount = . seconds( 10 )
45
44
}
46
-
45
+
47
46
let key : ConnectionPool . Key
48
47
let clientConfiguration : HTTPClient . Configuration
49
48
let tlsConfiguration : TLSConfiguration
@@ -59,7 +58,7 @@ extension HTTPConnectionPool {
59
58
self . clientConfiguration = clientConfiguration
60
59
self . sslContextCache = sslContextCache
61
60
self . tlsConfiguration = tlsConfiguration ?? clientConfiguration. tlsConfiguration ?? . forClient( )
62
-
61
+
63
62
var timeouts = timeouts
64
63
if let connect = clientConfiguration. timeout. connect {
65
64
timeouts. connect = connect
@@ -88,10 +87,10 @@ extension HTTPConnectionPool.ConnectionFactory {
88
87
case . http, . http_unix, . unix:
89
88
return self . makePlainChannel ( eventLoop: eventLoop) . map { ( $0, . http1_1) }
90
89
case . https, . https_unix:
91
- return self . makeTLSChannel ( eventLoop: eventLoop, logger: logger) . map {
92
- ( channel, negotiated) -> ( Channel , HTTPVersion ) in
93
- let version = negotiated == " h2 " ? HTTPVersion . http2 : HTTPVersion . http1_1
94
- return ( channel, version )
90
+ return self . makeTLSChannel ( eventLoop: eventLoop, logger: logger) . flatMapThrowing {
91
+ channel, negotiated in
92
+
93
+ ( channel, try self . matchALPNToHTTPVersion ( negotiated ) )
95
94
}
96
95
}
97
96
}
@@ -137,7 +136,9 @@ extension HTTPConnectionPool.ConnectionFactory {
137
136
return channel. eventLoop. makeFailedFuture ( error)
138
137
}
139
138
140
- return proxyHandler. proxyEstablishedFuture. flatMap {
139
+ // The proxyEstablishedFuture is set as soon as the HTTP1ProxyConnectHandler is in a
140
+ // pipeline. It is created in HTTP1ProxyConnectHandler's handlerAdded method.
141
+ return proxyHandler. proxyEstablishedFuture!. flatMap {
141
142
channel. pipeline. removeHandler ( proxyHandler) . flatMap {
142
143
channel. pipeline. removeHandler ( decoder) . flatMap {
143
144
channel. pipeline. removeHandler ( encoder)
@@ -170,7 +171,9 @@ extension HTTPConnectionPool.ConnectionFactory {
170
171
return channel. eventLoop. makeFailedFuture ( error)
171
172
}
172
173
173
- return socksEventHandler. socksEstablishedFuture. flatMap {
174
+ // The socksEstablishedFuture is set as soon as the SOCKSEventsHandler is in a
175
+ // pipeline. It is created in SOCKSEventsHandler's handlerAdded method.
176
+ return socksEventHandler. socksEstablishedFuture!. flatMap {
174
177
channel. pipeline. removeHandler ( socksEventHandler) . flatMap {
175
178
channel. pipeline. removeHandler ( socksConnectHandler)
176
179
}
@@ -206,18 +209,16 @@ extension HTTPConnectionPool.ConnectionFactory {
206
209
)
207
210
try channel. pipeline. syncOperations. addHandler ( sslHandler)
208
211
try channel. pipeline. syncOperations. addHandler ( tlsEventHandler)
209
- return tlsEventHandler. tlsEstablishedFuture
212
+
213
+ // The tlsEstablishedFuture is set as soon as the TLSEventsHandler is in a
214
+ // pipeline. It is created in TLSEventsHandler's handlerAdded method.
215
+ return tlsEventHandler. tlsEstablishedFuture!
210
216
} catch {
211
217
return channel. eventLoop. makeFailedFuture ( error)
212
218
}
213
219
} . flatMap { negotiated -> EventLoopFuture < ( Channel , HTTPVersion ) > in
214
- channel. pipeline. removeHandler ( tlsEventHandler) . map {
215
- switch negotiated {
216
- case " h2 " :
217
- return ( channel, . http2)
218
- default :
219
- return ( channel, . http1_1)
220
- }
220
+ channel. pipeline. removeHandler ( tlsEventHandler) . flatMapThrowing {
221
+ ( channel, try self . matchALPNToHTTPVersion ( negotiated) )
221
222
}
222
223
}
223
224
}
@@ -263,8 +264,13 @@ extension HTTPConnectionPool.ConnectionFactory {
263
264
preconditionFailure ( " Unexpected scheme " )
264
265
}
265
266
} . flatMap { channel -> EventLoopFuture < ( Channel , String ? ) > in
267
+ // It is save to use `try!` here, since we are sure, that a `TLSEventsHandler` exists
268
+ // within the pipeline. It is added in `makeTLSBootstrap`.
266
269
let tlsEventHandler = try ! channel. pipeline. syncOperations. handler ( type: TLSEventsHandler . self)
267
- return tlsEventHandler. tlsEstablishedFuture. flatMap { negotiated in
270
+
271
+ // The tlsEstablishedFuture is set as soon as the TLSEventsHandler is in a
272
+ // pipeline. It is created in TLSEventsHandler's handlerAdded method.
273
+ return tlsEventHandler. tlsEstablishedFuture!. flatMap { negotiated in
268
274
channel. pipeline. removeHandler ( tlsEventHandler) . map { ( channel, negotiated) }
269
275
}
270
276
}
@@ -343,6 +349,17 @@ extension HTTPConnectionPool.ConnectionFactory {
343
349
344
350
return eventLoop. makeSucceededFuture ( bootstrap)
345
351
}
352
+
353
+ private func matchALPNToHTTPVersion( _ negotiated: String ? ) throws -> HTTPVersion {
354
+ switch negotiated {
355
+ case . none, . some( " http/1.1 " ) :
356
+ return . http1_1
357
+ case . some( " h2 " ) :
358
+ return . http2
359
+ case . some( let unsupported) :
360
+ throw HTTPClientError . serverOfferedUnsupportedApplicationProtocol ( unsupported)
361
+ }
362
+ }
346
363
}
347
364
348
365
extension ConnectionPool . Key . Scheme {
0 commit comments