@@ -97,6 +97,13 @@ public NettyRequestSender(AsyncHttpClientConfig config, ChannelManager channelMa
9797 requestFactory = new NettyRequestFactory (config );
9898 }
9999
100+ // needConnect returns true if the request is secure/websocket and a HTTP proxy is set
101+ private boolean needConnect (final Request request , final ProxyServer proxyServer ) {
102+ return proxyServer != null
103+ && proxyServer .getProxyType ().isHttp ()
104+ && (request .getUri ().isSecured () || request .getUri ().isWebSocket ());
105+ }
106+
100107 public <T > ListenableFuture <T > sendRequest (final Request request , final AsyncHandler <T > asyncHandler , NettyResponseFuture <T > future ) {
101108 if (isClosed ()) {
102109 throw new IllegalStateException ("Closed" );
@@ -106,9 +113,7 @@ public <T> ListenableFuture<T> sendRequest(final Request request, final AsyncHan
106113 ProxyServer proxyServer = getProxyServer (config , request );
107114
108115 // WebSockets use connect tunneling to work with proxies
109- if (proxyServer != null && proxyServer .getProxyType ().isHttp () &&
110- (request .getUri ().isSecured () || request .getUri ().isWebSocket ()) &&
111- !isConnectAlreadyDone (request , future )) {
116+ if (needConnect (request , proxyServer ) && !isConnectAlreadyDone (request , future )) {
112117 // Proxy with HTTPS or WebSocket: CONNECT for sure
113118 if (future != null && future .isConnectAllowed ()) {
114119 // Perform CONNECT
@@ -125,6 +130,8 @@ public <T> ListenableFuture<T> sendRequest(final Request request, final AsyncHan
125130
126131 private static boolean isConnectAlreadyDone (Request request , NettyResponseFuture <?> future ) {
127132 return future != null
133+ // If the channel can't be reused or closed, a CONNECT is still required
134+ && future .isReuseChannel () && Channels .isChannelActive (future .channel ())
128135 && future .getNettyRequest () != null
129136 && future .getNettyRequest ().getHttpRequest ().method () == HttpMethod .CONNECT
130137 && !request .getMethod ().equals (CONNECT );
@@ -137,11 +144,19 @@ private static boolean isConnectAlreadyDone(Request request, NettyResponseFuture
137144 */
138145 private <T > ListenableFuture <T > sendRequestWithCertainForceConnect (Request request , AsyncHandler <T > asyncHandler , NettyResponseFuture <T > future ,
139146 ProxyServer proxyServer , boolean performConnectRequest ) {
140- NettyResponseFuture <T > newFuture = newNettyRequestAndResponseFuture (request , asyncHandler , future , proxyServer , performConnectRequest );
141147 Channel channel = getOpenChannel (future , request , proxyServer , asyncHandler );
142- return Channels .isChannelActive (channel )
143- ? sendRequestWithOpenChannel (newFuture , asyncHandler , channel )
144- : sendRequestWithNewChannel (request , proxyServer , newFuture , asyncHandler );
148+ if (Channels .isChannelActive (channel )) {
149+ NettyResponseFuture <T > newFuture = newNettyRequestAndResponseFuture (request , asyncHandler , future ,
150+ proxyServer , performConnectRequest );
151+ return sendRequestWithOpenChannel (newFuture , asyncHandler , channel );
152+ } else {
153+ // A new channel is not expected when performConnectRequest is false. We need to
154+ // revisit the condition of sending
155+ // the CONNECT request to the new channel.
156+ NettyResponseFuture <T > newFuture = newNettyRequestAndResponseFuture (request , asyncHandler , future ,
157+ proxyServer , needConnect (request , proxyServer ));
158+ return sendRequestWithNewChannel (request , proxyServer , newFuture , asyncHandler );
159+ }
145160 }
146161
147162 /**
0 commit comments