HTTPCLIENT-2177: fixed incorrect route state tracking by the async connect executor when negotiating a tunnel via a proxy

This commit is contained in:
Oleg Kalnichevski 2021-09-17 16:28:18 +02:00
parent 4ce032c92c
commit 90f69c87b2
1 changed files with 37 additions and 28 deletions

View File

@ -242,11 +242,14 @@ public final class AsyncConnectExec implements AsyncExecChainHandler {
})); }));
break; break;
case HttpRouteDirector.TUNNEL_TARGET: case HttpRouteDirector.TUNNEL_TARGET:
try { try {
final HttpHost proxy = route.getProxyHost(); final HttpHost proxy = route.getProxyHost();
final HttpHost target = route.getTargetHost(); final HttpHost target = route.getTargetHost();
createTunnel(state, proxy ,target, scope, chain, new AsyncExecCallback() { if (LOG.isDebugEnabled()) {
LOG.debug("{} create tunnel", exchangeId);
}
createTunnel(state, proxy, target, scope, chain, new AsyncExecCallback() {
@Override @Override
public AsyncDataConsumer handleResponse( public AsyncDataConsumer handleResponse(
@ -261,14 +264,35 @@ public final class AsyncConnectExec implements AsyncExecChainHandler {
asyncExecCallback.handleInformationResponse(response); asyncExecCallback.handleInformationResponse(response);
} }
@Override @Override
public void completed() { public void completed() {
if (LOG.isDebugEnabled()) { if (!execRuntime.isEndpointConnected()) {
LOG.debug("{} tunnel to target created", exchangeId); // 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 @Override
public void failed(final Exception cause) { public void failed(final Exception cause) {
@ -387,22 +411,7 @@ public final class AsyncConnectExec implements AsyncExecChainHandler {
@Override @Override
public void completed() { public void completed() {
if (!execRuntime.isEndpointConnected()) { asyncExecCallback.completed();
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();
}
}
} }
@Override @Override