@@ -39,7 +39,7 @@ public final class NIOHTTP1ProxyConnectHandler: ChannelDuplexHandler, RemovableC
39
39
private let targetPort : Int
40
40
private let headers : HTTPHeaders
41
41
private let deadline : NIODeadline
42
- private let promise : EventLoopPromise < Void > ?
42
+ private let promise : EventLoopPromise < Void >
43
43
44
44
/// Creates a new ``NIOHTTP1ProxyConnectHandler`` that issues a CONNECT request to a proxy server
45
45
/// and instructs the server to connect to `targetHost`.
@@ -53,7 +53,7 @@ public final class NIOHTTP1ProxyConnectHandler: ChannelDuplexHandler, RemovableC
53
53
targetPort: Int ,
54
54
headers: HTTPHeaders ,
55
55
deadline: NIODeadline ,
56
- promise: EventLoopPromise < Void > ? ) {
56
+ promise: EventLoopPromise < Void > ) {
57
57
self . targetHost = targetHost
58
58
self . targetPort = targetPort
59
59
self . headers = headers
@@ -62,7 +62,9 @@ public final class NIOHTTP1ProxyConnectHandler: ChannelDuplexHandler, RemovableC
62
62
}
63
63
64
64
public func handlerAdded( context: ChannelHandlerContext ) {
65
- self . sendConnect ( context: context)
65
+ if context. channel. isActive {
66
+ self . sendConnect ( context: context)
67
+ }
66
68
}
67
69
68
70
public func handlerRemoved( context: ChannelHandlerContext ) {
@@ -71,7 +73,7 @@ public final class NIOHTTP1ProxyConnectHandler: ChannelDuplexHandler, RemovableC
71
73
break
72
74
case . initialized, . connectSent, . headReceived:
73
75
self . state = . failed( Error . noResult)
74
- self . promise? . fail ( Error . noResult)
76
+ self . promise. fail ( Error . noResult)
75
77
}
76
78
}
77
79
@@ -143,23 +145,26 @@ public final class NIOHTTP1ProxyConnectHandler: ChannelDuplexHandler, RemovableC
143
145
}
144
146
145
147
private func handleHTTPHeadReceived( _ head: HTTPResponseHead , context: ChannelHandlerContext ) {
146
- guard case . connectSent( let scheduled) = self . state else {
147
- preconditionFailure ( " HTTPDecoder should throw an error, if we have not send a request " )
148
- }
149
-
150
- switch head. status. code {
151
- case 200 ..< 300 :
152
- // Any 2xx (Successful) response indicates that the sender (and all
153
- // inbound proxies) will switch to tunnel mode immediately after the
154
- // blank line that concludes the successful response's header section
155
- self . state = . headReceived( scheduled)
156
- case 407 :
157
- self . failWithError ( Error . proxyAuthenticationRequired, context: context)
158
-
159
- default :
160
- // Any response other than a successful response indicates that the tunnel
161
- // has not yet been formed and that the connection remains governed by HTTP.
162
- self . failWithError ( Error . invalidProxyResponse, context: context)
148
+ switch self . state {
149
+ case . connectSent( let scheduled) :
150
+ switch head. status. code {
151
+ case 200 ..< 300 :
152
+ // Any 2xx (Successful) response indicates that the sender (and all
153
+ // inbound proxies) will switch to tunnel mode immediately after the
154
+ // blank line that concludes the successful response's header section
155
+ self . state = . headReceived( scheduled)
156
+ case 407 :
157
+ self . failWithError ( Error . proxyAuthenticationRequired, context: context)
158
+
159
+ default :
160
+ // Any response other than a successful response indicates that the tunnel
161
+ // has not yet been formed and that the connection remains governed by HTTP.
162
+ self . failWithError ( Error . invalidProxyResponseHead ( head) , context: context)
163
+ }
164
+ case . failed, . completed:
165
+ break
166
+ case . initialized, . headReceived:
167
+ preconditionFailure ( " Invalid state: \( self . state) " )
163
168
}
164
169
}
165
170
@@ -182,7 +187,7 @@ public final class NIOHTTP1ProxyConnectHandler: ChannelDuplexHandler, RemovableC
182
187
case . headReceived( let timeout) :
183
188
timeout. cancel ( )
184
189
self . state = . completed
185
- self . promise? . succeed ( ( ) )
190
+ self . promise. succeed ( ( ) )
186
191
187
192
case . failed:
188
193
// ran into an error before... ignore this one
@@ -194,31 +199,35 @@ public final class NIOHTTP1ProxyConnectHandler: ChannelDuplexHandler, RemovableC
194
199
195
200
private func failWithError( _ error: Error , context: ChannelHandlerContext , closeConnection: Bool = true ) {
196
201
self . state = . failed( error)
197
- self . promise? . fail ( error)
202
+ self . promise. fail ( error)
198
203
context. fireErrorCaught ( error)
199
204
if closeConnection {
200
205
context. close ( mode: . all, promise: nil )
201
206
}
202
207
}
203
208
204
209
/// Error types for ``HTTP1ProxyConnectHandler``
205
- public struct Error : Swift . Error , CustomStringConvertible , Equatable {
206
- fileprivate enum ErrorEnum : String {
210
+ public struct Error : Swift . Error , Equatable {
211
+
212
+ fileprivate enum ErrorEnum : Equatable {
207
213
case proxyAuthenticationRequired
214
+ case invalidProxyResponseHead( head: HTTPResponseHead )
208
215
case invalidProxyResponse
209
216
case remoteConnectionClosed
210
217
case httpProxyHandshakeTimeout
211
218
case noResult
212
219
}
213
220
fileprivate let error : ErrorEnum
214
221
215
- /// return as String
216
- public var description : String { return error. rawValue }
217
-
218
222
/// Proxy response status `407` indicates that authentication is required
219
223
public static let proxyAuthenticationRequired = Error ( error: . proxyAuthenticationRequired)
220
224
221
- /// Proxy response contains unexpected status or body
225
+ /// Proxy response contains unexpected status
226
+ public static func invalidProxyResponseHead( _ head: HTTPResponseHead ) -> Error {
227
+ Error ( error: . invalidProxyResponseHead( head: head) )
228
+ }
229
+
230
+ /// Proxy response contains unexpected body
222
231
public static let invalidProxyResponse = Error ( error: . invalidProxyResponse)
223
232
224
233
/// Connection has been closed for ongoing request
@@ -229,4 +238,5 @@ public final class NIOHTTP1ProxyConnectHandler: ChannelDuplexHandler, RemovableC
229
238
230
239
/// Handler was removed before we received a result for the request
231
240
public static let noResult = Error ( error: . noResult)
232
- } }
241
+ }
242
+ }
0 commit comments