Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,17 @@ Rest5ClientBuilder restClient = Rest5Client

```

Preemptive Authentication can be disabled, which means that every request will be sent without authorization headers to see if it is accepted and, upon receiving an HTTP 401 response, it will resend the exact same request with the basic authentication header. If you wish to do this, then you can do so by disabling it via the `HttpAsyncClientBuilder`:
Preemptive Authentication can be disabled, which means that every request will be sent without authorization headers to see if it is accepted and, upon receiving an HTTP 401 response, it will resend the exact same request with the basic authentication header. If you wish to do this, then you can do so by disabling it via the `HttpClientConfigCallback`:

% :::{include-code} src={{doc-tests-src}}/rest5_client/RestClientDocumentation.java tag=rest-client-config-disable-preemptive-auth
```java
HttpHost host = new HttpHost("http", "localhost", 9200);

var creds = Base64.getEncoder().encodeToString("user:test-user-password".getBytes());

CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom()
.disableAuthCaching() // <1>
.build();

Rest5ClientBuilder restClient = Rest5Client
.builder(new HttpHost("https", "localhost", 9200))
.setHttpClient(httpclient)
.setHttpClientConfigCallback(HttpAsyncClientBuilder::disableAuthCaching)
.setDefaultHeaders(new Header[]{
new BasicHeader("Authorization", "Basic " + creds)
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ The Apache Http Async Client starts by default one dispatcher thread, and a numb

% :::{include-code} src={{doc-tests-src}}/rest5_client/RestClientDocumentation.java tag=rest-client-config-threads
```java
CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom()
.setIOReactorConfig(
IOReactorConfig.custom().setIoThreadCount(1).build()
)
.build();

Rest5ClientBuilder builder = Rest5Client
.builder(new HttpHost("localhost", 9200))
.setHttpClient(httpclient);
.setHttpClientConfigCallback(c -> c
.setIOReactorConfig(IOReactorConfig.custom()
.setIoThreadCount(1).build()
)
);
```
20 changes: 10 additions & 10 deletions docs/reference/transport/rest5-client/config/timeouts.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@

# Timeouts

Configuring requests timeouts can be done by providing an instance of `RequestConfigCallback` while building the `RestClient` through its builder. The interface has one method that receives an instance of [`org.apache.http.client.config.RequestConfig.Builder`](https://hc.apache.org/httpcomponents-client-4.5.x/current/httpclient/apidocs/org/apache/http/client/config/RequestConfig.Builder.html) as an argument and has the same return type. The request config builder can be modified and then returned. In the following example we increase the connect timeout (defaults to 1 second) and the socket timeout (defaults to 30 seconds).
Configuring requests timeouts can be done by using the `setRequestConfigCallback` method while building the `RestClient`. In the following example we increase the connect timeout (defaults to 30 second) and the response timeout (defaults to 0, which is infinite).

% :::{include-code} src={{doc-tests-src}}/rest5_client/RestClientDocumentation.java tag=rest-client-config-timeouts
```java
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
.setConnectTimeout(Timeout.of(5000, TimeUnit.MILLISECONDS));

CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom()
.setDefaultRequestConfig(requestConfigBuilder.build())
.build();

Rest5ClientBuilder builder = Rest5Client
.builder(new HttpHost("localhost", 9200))
.setHttpClient(httpclient);
.setRequestConfigCallback(r -> r
.setConnectTimeout(Timeout.of(5000, TimeUnit.MILLISECONDS))
.setResponseTimeout(Timeout.of(30000, TimeUnit.MILLISECONDS))
.build()
);
```

Timeouts also can be set per request with RequestOptions, which overrides RestClient customizeRequestConfig.
Timeouts also can be set per request with RequestOptions, which overrides RestClient's builder. The RequestOptions can then be set in the Rest5ClientTransport constructor.

% :::{include-code} src={{doc-tests-src}}/rest5_client/RestClientDocumentation.java tag=rest-client-config-request-options-timeouts
```java
Expand All @@ -29,5 +26,8 @@ RequestConfig requestConfig = RequestConfig.custom()
RequestOptions options = RequestOptions.DEFAULT.toBuilder()
.setRequestConfig(requestConfig)
.build();

ElasticsearchTransport transport = new Rest5ClientTransport(
restClient, new JacksonJsonpMapper(), options);
```

Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;

import static co.elastic.clients.transport.rest5_client.low_level.LanguageRuntimeVersions.getRuntimeMetadata;

Expand Down Expand Up @@ -75,6 +76,10 @@ public final class Rest5ClientBuilder {

private final List<Node> nodes;
private CloseableHttpAsyncClient httpClient;
private Consumer<HttpAsyncClientBuilder> httpClientConfigCallback;
private Consumer<RequestConfig.Builder> requestConfigCallback;
private Consumer<ConnectionConfig.Builder> connectionConfigCallback;
private Consumer<PoolingAsyncClientConnectionManagerBuilder> connectionManagerCallback;
private Header[] defaultHeaders = EMPTY_HEADERS;
private Rest5Client.FailureListener failureListener;
private SSLContext sslContext;
Expand Down Expand Up @@ -320,6 +325,58 @@ public Rest5ClientBuilder setMetaHeaderEnabled(boolean metadataEnabled) {
return this;
}

/**
* Allows to customize the {@link CloseableHttpAsyncClient} being created and used by the
* {@link Rest5Client}.
* Commonly used to customize {@link HttpAsyncClientBuilder} without losing any other useful default
* value that the {@link Rest5ClientBuilder} internally sets.
* @throws NullPointerException if {@code httpClientConfigCallback} is {@code null}.
*/
public Rest5ClientBuilder setHttpClientConfigCallback(Consumer<HttpAsyncClientBuilder> httpClientConfigCallback) {
Objects.requireNonNull(httpClientConfigCallback, "httpClientConfigCallback must not be null");
this.httpClientConfigCallback = httpClientConfigCallback;
return this;
}

/**
* Allows to customize the {@link RequestConfig} created by the {@link Rest5Client}
* and used by the {@link CloseableHttpAsyncClient}.
* Commonly used to customize {@link RequestConfig} without losing any other useful default
* value that the {@link Rest5ClientBuilder} internally sets.
* @throws NullPointerException if {@code requestConfigCallback} is {@code null}.
*/
public Rest5ClientBuilder setRequestConfigCallback(Consumer<RequestConfig.Builder> requestConfigCallback) {
Objects.requireNonNull(requestConfigCallback, "requestConfigCallback must not be null");
this.requestConfigCallback = requestConfigCallback;
return this;
}

/**
* Allows to customize the {@link ConnectionConfig} created by the {@link Rest5Client}
* and used by the {@link CloseableHttpAsyncClient}.
* Commonly used to customize {@link ConnectionConfig} without losing any other useful default
* value that the {@link Rest5ClientBuilder} internally sets.
* @throws NullPointerException if {@code connectionConfigCallback} is {@code null}.
*/
public Rest5ClientBuilder setConnectionConfigCallback(Consumer<ConnectionConfig.Builder> connectionConfigCallback) {
Objects.requireNonNull(connectionConfigCallback, "connectionConfigCallback must not be null");
this.connectionConfigCallback = connectionConfigCallback;
return this;
}

/**
* Allows to customize the {@link PoolingAsyncClientConnectionManager} created by the {@link Rest5Client}
* and used by the {@link CloseableHttpAsyncClient}.
* Commonly used to customize {@link PoolingAsyncClientConnectionManager} without losing any other useful default
* value that the {@link Rest5ClientBuilder} internally sets.
* @throws NullPointerException if {@code connectionManagerCallback} is {@code null}.
*/
public Rest5ClientBuilder setConnectionManagerCallback(Consumer<PoolingAsyncClientConnectionManagerBuilder> connectionManagerCallback) {
Objects.requireNonNull(connectionManagerCallback, "connectionManagerCallback must not be null");
this.connectionManagerCallback = connectionManagerCallback;
return this;
}

/**
* Creates a new {@link Rest5Client} based on the provided configuration.
*/
Expand Down Expand Up @@ -369,31 +426,40 @@ private CloseableHttpAsyncClient createHttpClient() {
return this.httpClient;
}
// otherwise, creating a default instance of CloseableHttpAsyncClient
// default timeouts are all 3 mins
RequestConfig requestConfigBuilder = RequestConfig.custom()

// default timeouts are all 3 mins, replacing those
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
.setConnectionRequestTimeout(Timeout.of(DEFAULT_SOCKET_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS))
.setResponseTimeout(Timeout.of(DEFAULT_RESPONSE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS))
.build();
.setResponseTimeout(Timeout.of(DEFAULT_RESPONSE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));

if (requestConfigCallback != null) {
requestConfigCallback.accept(requestConfigBuilder);
}

try {

SSLContext sslContext = this.sslContext != null ? this.sslContext : SSLContext.getDefault();

ConnectionConfig connectionConfig = ConnectionConfig.custom()
.setConnectTimeout(Timeout.of(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS))
.build();
ConnectionConfig.Builder connectionConfigBuilder = ConnectionConfig.custom()
.setConnectTimeout(Timeout.of(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
if (connectionConfigCallback != null) {
connectionConfigCallback.accept(connectionConfigBuilder);
}

PoolingAsyncClientConnectionManager defaultConnectionManager =
PoolingAsyncClientConnectionManagerBuilder connectionManagerBuilder =
PoolingAsyncClientConnectionManagerBuilder.create()
.setDefaultConnectionConfig(connectionConfig)
.setDefaultConnectionConfig(connectionConfigBuilder.build())
.setMaxConnPerRoute(DEFAULT_MAX_CONN_PER_ROUTE)
.setMaxConnTotal(DEFAULT_MAX_CONN_TOTAL)
.setTlsStrategy(new BasicClientTlsStrategy(sslContext))
.build();
.setTlsStrategy(new BasicClientTlsStrategy(sslContext));

if (connectionManagerCallback != null) {
connectionManagerCallback.accept(connectionManagerBuilder);
}

HttpAsyncClientBuilder httpClientBuilder = HttpAsyncClientBuilder.create()
.setDefaultRequestConfig(requestConfigBuilder)
.setConnectionManager(defaultConnectionManager)
.setDefaultRequestConfig(requestConfigBuilder.build())
.setConnectionManager(connectionManagerBuilder.build())
.setUserAgent(USER_AGENT_HEADER_VALUE)
.setTargetAuthenticationStrategy(new DefaultAuthenticationStrategy())
.setThreadFactory(new RestClientThreadFactory());
Expand All @@ -407,6 +473,9 @@ private CloseableHttpAsyncClient createHttpClient() {
if (this.routePlanner != null) {
httpClientBuilder.setRoutePlanner(this.routePlanner);
}
if (httpClientConfigCallback != null) {
httpClientConfigCallback.accept(httpClientBuilder);
}

return httpClientBuilder.build();
} catch (NoSuchAlgorithmException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@
import co.elastic.clients.transport.rest5_client.low_level.Rest5Client;
import co.elastic.clients.transport.rest5_client.low_level.Rest5ClientBuilder;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.core5.http.ContentType;
Expand Down Expand Up @@ -183,13 +182,11 @@ public void onFailure(Node node) {
.setMaxConnPerRoute(5)
.build();

CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom()
.setConnectionManager(connectionManager)
.build();

Rest5ClientBuilder builder = Rest5Client
.builder(new HttpHost("http", "localhost", 9200))
.setHttpClient(httpclient);
.setHttpClientConfigCallback(c -> c
.setConnectionManager(connectionManager)
);
//end::rest-client-init-request-config-callback
}

Expand Down Expand Up @@ -319,13 +316,10 @@ public void commonConfiguration() throws Exception {
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
.setConnectTimeout(Timeout.of(5000, TimeUnit.MILLISECONDS));

CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom()
.setDefaultRequestConfig(requestConfigBuilder.build())
.build();

Rest5ClientBuilder builder = Rest5Client
.builder(new HttpHost("localhost", 9200))
.setHttpClient(httpclient);
.setHttpClientConfigCallback(c -> c
.setDefaultRequestConfig(requestConfigBuilder.build()));
//end::rest-client-config-timeouts
}
{
Expand All @@ -342,15 +336,12 @@ public void commonConfiguration() throws Exception {
}
{
//tag::rest-client-config-threads
CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom()
.setIOReactorConfig(
IOReactorConfig.custom().setIoThreadCount(1).build()
)
.build();

Rest5ClientBuilder builder = Rest5Client
.builder(new HttpHost("localhost", 9200))
.setHttpClient(httpclient);
.setHttpClientConfigCallback(c -> c
.setIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(1).build()
));
//end::rest-client-config-threads
}
{
Expand All @@ -372,13 +363,9 @@ public void commonConfiguration() throws Exception {

var creds = Base64.getEncoder().encodeToString("user:test-user-password".getBytes());

CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom()
.disableAuthCaching() // <1>
.build();

Rest5ClientBuilder restClient = Rest5Client
.builder(new HttpHost("https", "localhost", 9200))
.setHttpClient(httpclient)
.setHttpClientConfigCallback(HttpAsyncClientBuilder::disableAuthCaching) // <1>
.setDefaultHeaders(new Header[]{
new BasicHeader("Authorization", "Basic " + creds)
});
Expand Down
Loading