HTTPCLIENT-1924: HttpClient to shut down the connection manager if a fatal error occurs in the course of a request execution

This commit is contained in:
Oleg Kalnichevski 2018-06-17 10:35:28 +02:00
parent 6570228118
commit ec22a46866
4 changed files with 23 additions and 11 deletions

View File

@ -788,7 +788,7 @@ public class HttpClientBuilder {
final NamedElementChain<ExecChainHandler> execChainDefinition = new NamedElementChain<>();
execChainDefinition.addLast(
new MainClientExec(reuseStrategyCopy, keepAliveStrategyCopy, userTokenHandlerCopy),
new MainClientExec(connManagerCopy, reuseStrategyCopy, keepAliveStrategyCopy, userTokenHandlerCopy),
ChainElements.MAIN_TRANSPORT.name());
execChainDefinition.addFirst(
new ConnectExec(

View File

@ -37,6 +37,7 @@ import org.apache.hc.client5.http.classic.ExecChain;
import org.apache.hc.client5.http.classic.ExecChainHandler;
import org.apache.hc.client5.http.classic.ExecRuntime;
import org.apache.hc.client5.http.impl.ConnectionShutdownException;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
@ -46,6 +47,7 @@ import org.apache.hc.core5.http.ConnectionReuseStrategy;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.message.RequestLine;
import org.apache.hc.core5.io.ShutdownType;
import org.apache.hc.core5.util.Args;
import org.apache.hc.core5.util.TimeValue;
import org.slf4j.Logger;
@ -63,6 +65,7 @@ final class MainClientExec implements ExecChainHandler {
private final Logger log = LoggerFactory.getLogger(getClass());
private final HttpClientConnectionManager connectionManager;
private final ConnectionReuseStrategy reuseStrategy;
private final ConnectionKeepAliveStrategy keepAliveStrategy;
private final UserTokenHandler userTokenHandler;
@ -71,15 +74,14 @@ final class MainClientExec implements ExecChainHandler {
* @since 4.4
*/
public MainClientExec(
final HttpClientConnectionManager connectionManager,
final ConnectionReuseStrategy reuseStrategy,
final ConnectionKeepAliveStrategy keepAliveStrategy,
final UserTokenHandler userTokenHandler) {
Args.notNull(reuseStrategy, "Connection reuse strategy");
Args.notNull(keepAliveStrategy, "Connection keep alive strategy");
Args.notNull(userTokenHandler, "User token handler");
this.reuseStrategy = reuseStrategy;
this.keepAliveStrategy = keepAliveStrategy;
this.userTokenHandler = userTokenHandler;
this.connectionManager = Args.notNull(connectionManager, "Connection manager");
this.reuseStrategy = Args.notNull(reuseStrategy, "Connection reuse strategy");
this.keepAliveStrategy = Args.notNull(keepAliveStrategy, "Connection keep alive strategy");
this.userTokenHandler = Args.notNull(userTokenHandler, "User token handler");
}
@Override
@ -147,6 +149,9 @@ final class MainClientExec implements ExecChainHandler {
} catch (final HttpException | RuntimeException | IOException ex) {
execRuntime.discardConnection();
throw ex;
} catch (final Error error) {
connectionManager.shutdown(ShutdownType.IMMEDIATE);
throw error;
}
}

View File

@ -61,6 +61,7 @@ import org.apache.hc.core5.http.protocol.HttpProcessor;
import org.apache.hc.core5.http.protocol.RequestContent;
import org.apache.hc.core5.http.protocol.RequestTargetHost;
import org.apache.hc.core5.http.protocol.RequestUserAgent;
import org.apache.hc.core5.io.ShutdownType;
import org.apache.hc.core5.net.URIAuthority;
import org.apache.hc.core5.util.Args;
import org.apache.hc.core5.util.VersionInfo;
@ -159,12 +160,15 @@ public class MinimalHttpClient extends CloseableHttpClient {
ioex.initCause(ex);
execRuntime.discardConnection();
throw ioex;
} catch (final RuntimeException | IOException ex) {
execRuntime.discardConnection();
throw ex;
} catch (final HttpException httpException) {
execRuntime.discardConnection();
throw new ClientProtocolException(httpException);
} catch (final RuntimeException | IOException ex) {
execRuntime.discardConnection();
throw ex;
} catch (final Error error) {
connManager.shutdown(ShutdownType.IMMEDIATE);
throw error;
}
}

View File

@ -38,6 +38,7 @@ import org.apache.hc.client5.http.classic.ExecRuntime;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.entity.EntityBuilder;
import org.apache.hc.client5.http.impl.ConnectionShutdownException;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
@ -58,6 +59,8 @@ import org.mockito.stubbing.Answer;
@SuppressWarnings({"boxing","static-access"}) // test code
public class TestMainClientExec {
@Mock
private HttpClientConnectionManager connectionManager;
@Mock
private ConnectionReuseStrategy reuseStrategy;
@Mock
@ -73,7 +76,7 @@ public class TestMainClientExec {
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
mainClientExec = new MainClientExec(reuseStrategy, keepAliveStrategy, userTokenHandler);
mainClientExec = new MainClientExec(connectionManager, reuseStrategy, keepAliveStrategy, userTokenHandler);
target = new HttpHost("foo", 80);
}