diff --git a/nima/http2/webclient/src/main/java/io/helidon/nima/http2/webclient/ClientRequestImpl.java b/nima/http2/webclient/src/main/java/io/helidon/nima/http2/webclient/ClientRequestImpl.java index b999c87a212..cd8a489ef4b 100644 --- a/nima/http2/webclient/src/main/java/io/helidon/nima/http2/webclient/ClientRequestImpl.java +++ b/nima/http2/webclient/src/main/java/io/helidon/nima/http2/webclient/ClientRequestImpl.java @@ -226,6 +226,12 @@ public Http2ClientRequest property(String propertyName, String propertyValue) { return this; } + @Override + public Http2ClientRequest keepAlive(boolean keepAlive) { + //NOOP + return this; + } + @Override public Http2ClientRequest priority(int priority) { if (priority < 1 || priority > 256) { diff --git a/nima/tests/integration/webclient/webclient/src/test/java/io/helidon/nima/webclient/http1/ClientRequestImplTest.java b/nima/tests/integration/webclient/webclient/src/test/java/io/helidon/nima/webclient/http1/ClientRequestImplTest.java index 0a4596dc049..8f60e66fde6 100644 --- a/nima/tests/integration/webclient/webclient/src/test/java/io/helidon/nima/webclient/http1/ClientRequestImplTest.java +++ b/nima/tests/integration/webclient/webclient/src/test/java/io/helidon/nima/webclient/http1/ClientRequestImplTest.java @@ -219,7 +219,8 @@ void testConnectionQueueDequeue() { connectionNow = ConnectionCache.connection(requestImpl.clientConfig(), null, requestImpl.uri(), - requestImpl.headers()); + requestImpl.headers(), + requestImpl.keepAlive()); request.connection(connectionNow); Http1ClientResponse response = request.request(); // connection will be queued up @@ -242,9 +243,10 @@ void testConnectionQueueSizeLimit() { Http1ClientRequest request = injectedHttp1client.put("/test"); ClientRequestImpl requestImpl = (ClientRequestImpl) request; connectionList.add(ConnectionCache.connection(requestImpl.clientConfig(), - null, - requestImpl.uri(), - requestImpl.headers())); + null, + requestImpl.uri(), + requestImpl.headers(), + requestImpl.keepAlive())); request.connection(connectionList.get(i)); responseList.add(request.request()); } @@ -261,9 +263,10 @@ void testConnectionQueueSizeLimit() { Http1ClientRequest request = injectedHttp1client.put("/test"); ClientRequestImpl requestImpl = (ClientRequestImpl) request; connection = ConnectionCache.connection(requestImpl.clientConfig(), - null, - requestImpl.uri(), - requestImpl.headers()); + null, + requestImpl.uri(), + requestImpl.headers(), + requestImpl.keepAlive()); request.connection(connection); response = request.request(); if (i < connectionQueueSize) { @@ -280,9 +283,10 @@ void testConnectionQueueSizeLimit() { Http1ClientRequest request = injectedHttp1client.put("/test"); ClientRequestImpl requestImpl = (ClientRequestImpl) request; ClientConnection connectionNow = ConnectionCache.connection(requestImpl.clientConfig(), - null, - requestImpl.uri(), - requestImpl.headers()); + null, + requestImpl.uri(), + requestImpl.headers(), + requestImpl.keepAlive()); request.connection(connectionNow); Http1ClientResponse responseNow = request.request(); // Verify that the connection was dequeued diff --git a/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/ClientRequest.java b/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/ClientRequest.java index 7c720d0304e..0d7074b31a5 100644 --- a/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/ClientRequest.java +++ b/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/ClientRequest.java @@ -274,6 +274,14 @@ default T request(Class type) { */ B property(String propertyName, String propertyValue); + /** + * Whether to use keep alive with this request. + * + * @param keepAlive use keep alive + * @return updated client request + */ + B keepAlive(boolean keepAlive); + /** * Handle output stream. */ diff --git a/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/ClientRequestImpl.java b/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/ClientRequestImpl.java index e336a1b3e39..a2a03612b2d 100644 --- a/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/ClientRequestImpl.java +++ b/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/ClientRequestImpl.java @@ -66,6 +66,7 @@ class ClientRequestImpl implements Http1ClientRequest { private ClientConnection connection; private UriFragment fragment = UriFragment.empty(); private boolean skipUriEncoding = false; + private boolean keepAlive; ClientRequestImpl(Http1ClientConfig clientConfig, Http.Method method, @@ -82,6 +83,7 @@ class ClientRequestImpl implements Http1ClientRequest { this.maxRedirects = clientConfig.maxRedirects(); this.tls = clientConfig.tls().orElse(null); this.query = query; + this.keepAlive = clientConfig.defaultKeepAlive(); this.requestId = "http1-client-" + COUNTER.getAndIncrement(); this.explicitHeaders = WritableHeaders.create(clientConfig.defaultHeaders()); @@ -199,7 +201,8 @@ public Http1ClientResponse outputStream(OutputStreamHandler streamHandler) { rejectHeadWithEntity(); CompletableFuture whenSent = new CompletableFuture<>(); CompletableFuture whenComplete = new CompletableFuture<>(); - WebClientService.Chain callChain = new HttpCallOutputStreamChain(clientConfig, + WebClientService.Chain callChain = new HttpCallOutputStreamChain(this, + clientConfig, connection, tls, whenSent, @@ -244,6 +247,12 @@ public Http1ClientRequest property(String propertyName, String propertyValue) { return this; } + @Override + public Http1ClientRequest keepAlive(boolean keepAlive) { + this.keepAlive = keepAlive; + return this; + } + Http1ClientConfig clientConfig() { return clientConfig; } @@ -252,6 +261,10 @@ UriHelper uri() { return uri; } + boolean keepAlive() { + return keepAlive; + } + @Override public ClientRequestHeaders headers() { return ClientRequestHeaders.create(explicitHeaders); @@ -306,7 +319,8 @@ private ClientResponseImpl invokeWithFollowRedirectsEntity(Object entity) { private ClientResponseImpl invokeRequestWithEntity(Object entity) { CompletableFuture whenSent = new CompletableFuture<>(); CompletableFuture whenComplete = new CompletableFuture<>(); - WebClientService.Chain callChain = new HttpCallEntityChain(clientConfig, + WebClientService.Chain callChain = new HttpCallEntityChain(this, + clientConfig, connection, tls, whenSent, diff --git a/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/ConnectionCache.java b/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/ConnectionCache.java index e823cd25fb4..818e92b15de 100644 --- a/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/ConnectionCache.java +++ b/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/ConnectionCache.java @@ -44,8 +44,9 @@ private ConnectionCache() { static ClientConnection connection(Http1ClientConfig clientConfig, Tls tls, UriHelper uri, - ClientRequestHeaders headers) { - boolean keepAlive = handleKeepAlive(clientConfig.defaultKeepAlive(), headers); + ClientRequestHeaders headers, + boolean defaultKeepAlive) { + boolean keepAlive = handleKeepAlive(defaultKeepAlive, headers); Tls effectiveTls = HTTPS.equals(uri.scheme()) ? tls : null; if (keepAlive) { return keepAliveConnection(clientConfig, effectiveTls, uri); diff --git a/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/HttpCallChainBase.java b/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/HttpCallChainBase.java index e67af09c502..30872a14fb8 100644 --- a/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/HttpCallChainBase.java +++ b/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/HttpCallChainBase.java @@ -38,13 +38,16 @@ abstract class HttpCallChainBase implements WebClientService.Chain { private final Http1ClientConfig clientConfig; private final ClientConnection connection; private final Tls tls; + private final boolean keepAlive; HttpCallChainBase(Http1ClientConfig clientConfig, ClientConnection connection, - Tls tls) { + Tls tls, + boolean keepAlive) { this.clientConfig = clientConfig; this.connection = connection; this.tls = tls; + this.keepAlive = keepAlive; } static void writeHeaders(Headers headers, BufferData bufferData, boolean validate) { @@ -105,6 +108,7 @@ private ClientConnection obtainConnection(WebClientServiceRequest request) { return ConnectionCache.connection(clientConfig, tls, request.uri(), - request.headers()); + request.headers(), + keepAlive); } } diff --git a/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/HttpCallEntityChain.java b/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/HttpCallEntityChain.java index a929b3a17d5..b5760523691 100644 --- a/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/HttpCallEntityChain.java +++ b/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/HttpCallEntityChain.java @@ -39,13 +39,14 @@ class HttpCallEntityChain extends HttpCallChainBase { private final CompletableFuture whenComplete; private final Object entity; - HttpCallEntityChain(Http1ClientConfig clientConfig, + HttpCallEntityChain(ClientRequestImpl request, + Http1ClientConfig clientConfig, ClientConnection connection, Tls tls, CompletableFuture whenSent, CompletableFuture whenComplete, Object entity) { - super(clientConfig, connection, tls); + super(clientConfig, connection, tls, request.keepAlive()); this.clientConfig = clientConfig; this.whenSent = whenSent; this.whenComplete = whenComplete; diff --git a/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/HttpCallOutputStreamChain.java b/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/HttpCallOutputStreamChain.java index 5aa2f0830de..b96dc292f2c 100644 --- a/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/HttpCallOutputStreamChain.java +++ b/nima/webclient/webclient/src/main/java/io/helidon/nima/webclient/http1/HttpCallOutputStreamChain.java @@ -42,13 +42,14 @@ class HttpCallOutputStreamChain extends HttpCallChainBase { private final CompletableFuture whenComplete; private final ClientRequest.OutputStreamHandler osHandler; - HttpCallOutputStreamChain(Http1ClientConfig clientConfig, + HttpCallOutputStreamChain(ClientRequestImpl clientRequest, + Http1ClientConfig clientConfig, ClientConnection connection, Tls tls, CompletableFuture whenSent, CompletableFuture whenComplete, ClientRequest.OutputStreamHandler osHandler) { - super(clientConfig, connection, tls); + super(clientConfig, connection, tls, clientRequest.keepAlive()); this.clientConfig = clientConfig; this.whenSent = whenSent; this.whenComplete = whenComplete; diff --git a/nima/webclient/webclient/src/test/java/io/helidon/nima/webclient/HttpClientTest.java b/nima/webclient/webclient/src/test/java/io/helidon/nima/webclient/HttpClientTest.java index 379060c882d..d705ff48ce8 100644 --- a/nima/webclient/webclient/src/test/java/io/helidon/nima/webclient/HttpClientTest.java +++ b/nima/webclient/webclient/src/test/java/io/helidon/nima/webclient/HttpClientTest.java @@ -188,5 +188,10 @@ public FakeHttpClientRequest skipUriEncoding() { public FakeHttpClientRequest property(String propertyName, String propertyValue) { return null; } + + @Override + public FakeHttpClientRequest keepAlive(boolean keepAlive) { + return this; + } } }