You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2021/09/18 19:36:25 UTC

[httpcomponents-client] 02/04: HTTPCLIENT-2177: fixed incorrect route state tracking by the async connect executor when negotiating a tunnel via a proxy

This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-client.git

commit 90f69c87b27b721ea8f0e23bdb4baf92bd7cde06
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Fri Sep 17 16:28:18 2021 +0200

    HTTPCLIENT-2177: fixed incorrect route state tracking by the async connect executor when negotiating a tunnel via a proxy
---
 .../client5/http/impl/async/AsyncConnectExec.java  | 65 ++++++++++++----------
 1 file changed, 37 insertions(+), 28 deletions(-)

diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AsyncConnectExec.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AsyncConnectExec.java
index 0ca255e..b0288c7 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AsyncConnectExec.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AsyncConnectExec.java
@@ -242,11 +242,14 @@ public final class AsyncConnectExec implements AsyncExecChainHandler {
                 }));
                 break;
 
-            case HttpRouteDirector.TUNNEL_TARGET:
-                try {
-                    final HttpHost proxy = route.getProxyHost();
-                    final HttpHost target = route.getTargetHost();
-                    createTunnel(state, proxy ,target, scope, chain, new AsyncExecCallback() {
+                case HttpRouteDirector.TUNNEL_TARGET:
+                    try {
+                        final HttpHost proxy = route.getProxyHost();
+                        final HttpHost target = route.getTargetHost();
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug("{} create tunnel", exchangeId);
+                        }
+                        createTunnel(state, proxy, target, scope, chain, new AsyncExecCallback() {
 
                         @Override
                         public AsyncDataConsumer handleResponse(
@@ -261,14 +264,35 @@ public final class AsyncConnectExec implements AsyncExecChainHandler {
                             asyncExecCallback.handleInformationResponse(response);
                         }
 
-                        @Override
-                        public void completed() {
-                            if (LOG.isDebugEnabled()) {
-                                LOG.debug("{} tunnel to target created", exchangeId);
+                            @Override
+                            public void completed() {
+                                if (!execRuntime.isEndpointConnected()) {
+                                    // Remote endpoint disconnected. Need to start over
+                                    if (LOG.isDebugEnabled()) {
+                                        LOG.debug("{} proxy disconnected", exchangeId);
+                                    }
+                                    state.tracker.reset();
+                                }
+                                if (state.challenged) {
+                                    if (LOG.isDebugEnabled()) {
+                                        LOG.debug("{} proxy authentication required", exchangeId);
+                                    }
+                                    proceedToNextHop(state, request, entityProducer, scope, chain, asyncExecCallback);
+                                } else {
+                                    if (state.tunnelRefused) {
+                                        if (LOG.isDebugEnabled()) {
+                                            LOG.debug("{} tunnel refused", exchangeId);
+                                        }
+                                        asyncExecCallback.failed(new TunnelRefusedException("Tunnel refused", null));
+                                    } else {
+                                        if (LOG.isDebugEnabled()) {
+                                            LOG.debug("{} tunnel to target created", exchangeId);
+                                        }
+                                        tracker.tunnelTarget(false);
+                                        proceedToNextHop(state, request, entityProducer, scope, chain, asyncExecCallback);
+                                    }
+                                }
                             }
-                            tracker.tunnelTarget(false);
-                            proceedToNextHop(state, request, entityProducer, scope, chain, asyncExecCallback);
-                        }
 
                         @Override
                         public void failed(final Exception cause) {
@@ -387,22 +411,7 @@ public final class AsyncConnectExec implements AsyncExecChainHandler {
 
             @Override
             public void completed() {
-                if (!execRuntime.isEndpointConnected()) {
-                    state.tracker.reset();
-                }
-                if (state.challenged) {
-                    try {
-                        createTunnel(state, proxy, nextHop, scope, chain, asyncExecCallback);
-                    } catch (final HttpException | IOException ex) {
-                        asyncExecCallback.failed(ex);
-                    }
-                } else {
-                    if (state.tunnelRefused) {
-                        asyncExecCallback.failed(new TunnelRefusedException("Tunnel refused", null));
-                    } else {
-                        asyncExecCallback.completed();
-                    }
-                }
+                asyncExecCallback.completed();
             }
 
             @Override