Made handling of refused tunnel exception consistent between the classic and async protocol handler implementations; Proxy response body no longer gets buffered in memory in order to avoid excessive resource allocation in case of a proxy misbehavior
This commit is contained in:
parent
5eb15a1be4
commit
a0a38afbee
|
@ -122,6 +122,7 @@ public final class AsyncConnectExec implements AsyncExecChainHandler {
|
||||||
|
|
||||||
volatile boolean challenged;
|
volatile boolean challenged;
|
||||||
volatile boolean tunnelRefused;
|
volatile boolean tunnelRefused;
|
||||||
|
volatile HttpResponse tunnelResponse;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +295,7 @@ public final class AsyncConnectExec implements AsyncExecChainHandler {
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debug("{} tunnel refused", exchangeId);
|
LOG.debug("{} tunnel refused", exchangeId);
|
||||||
}
|
}
|
||||||
asyncExecCallback.failed(new TunnelRefusedException("Tunnel refused", null));
|
asyncExecCallback.failed(new TunnelRefusedException("CONNECT refused by proxy: " + new StatusLine(state.tunnelResponse), null));
|
||||||
} else {
|
} else {
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debug("{} tunnel to target created", exchangeId);
|
LOG.debug("{} tunnel to target created", exchangeId);
|
||||||
|
@ -455,7 +456,8 @@ public final class AsyncConnectExec implements AsyncExecChainHandler {
|
||||||
state.challenged = false;
|
state.challenged = false;
|
||||||
if (status >= HttpStatus.SC_REDIRECTION) {
|
if (status >= HttpStatus.SC_REDIRECTION) {
|
||||||
state.tunnelRefused = true;
|
state.tunnelRefused = true;
|
||||||
entityConsumerRef.set(asyncExecCallback.handleResponse(response, entityDetails));
|
state.tunnelResponse = response;
|
||||||
|
entityConsumerRef.set(null);
|
||||||
} else if (status == HttpStatus.SC_OK) {
|
} else if (status == HttpStatus.SC_OK) {
|
||||||
asyncExecCallback.completed();
|
asyncExecCallback.completed();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -282,12 +282,9 @@ public final class ConnectExec implements ExecChainHandler {
|
||||||
|
|
||||||
final int status = response.getCode();
|
final int status = response.getCode();
|
||||||
if (status != HttpStatus.SC_OK) {
|
if (status != HttpStatus.SC_OK) {
|
||||||
|
EntityUtils.consume(response.getEntity());
|
||||||
// Buffer response content
|
|
||||||
final HttpEntity entity = response.getEntity();
|
|
||||||
final String responseMessage = entity != null ? EntityUtils.toString(entity) : null;
|
|
||||||
execRuntime.disconnectEndpoint();
|
execRuntime.disconnectEndpoint();
|
||||||
throw new TunnelRefusedException("CONNECT refused by proxy: " + new StatusLine(response), responseMessage);
|
throw new TunnelRefusedException("CONNECT refused by proxy: " + new StatusLine(response), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// How to decide on security of the tunnelled connection?
|
// How to decide on security of the tunnelled connection?
|
||||||
|
|
|
@ -200,12 +200,9 @@ public class ProxyClient {
|
||||||
final int status = response.getCode();
|
final int status = response.getCode();
|
||||||
|
|
||||||
if (status > 299) {
|
if (status > 299) {
|
||||||
|
EntityUtils.consume(response.getEntity());
|
||||||
// Buffer response content
|
|
||||||
final HttpEntity entity = response.getEntity();
|
|
||||||
final String responseMessage = entity != null ? EntityUtils.toString(entity) : null;
|
|
||||||
conn.close();
|
conn.close();
|
||||||
throw new TunnelRefusedException("CONNECT refused by proxy: " + new StatusLine(response), responseMessage);
|
throw new TunnelRefusedException("CONNECT refused by proxy: " + new StatusLine(response), null);
|
||||||
}
|
}
|
||||||
return conn.getSocket();
|
return conn.getSocket();
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,9 +218,7 @@ public class TestConnectExec {
|
||||||
Mockito.any())).thenReturn(response);
|
Mockito.any())).thenReturn(response);
|
||||||
|
|
||||||
final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context);
|
final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context);
|
||||||
final TunnelRefusedException exception = Assertions.assertThrows(TunnelRefusedException.class, () ->
|
Assertions.assertThrows(TunnelRefusedException.class, () -> exec.execute(request, scope, execChain));
|
||||||
exec.execute(request, scope, execChain));
|
|
||||||
Assertions.assertEquals("Ka-boom", exception.getResponseMessage());
|
|
||||||
Mockito.verify(execRuntime, Mockito.atLeastOnce()).disconnectEndpoint();
|
Mockito.verify(execRuntime, Mockito.atLeastOnce()).disconnectEndpoint();
|
||||||
Mockito.verify(execRuntime).discardEndpoint();
|
Mockito.verify(execRuntime).discardEndpoint();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue