2017-02-24 07:52:36 -05:00
|
|
|
=== Common configuration
|
2016-07-29 05:22:47 -04:00
|
|
|
|
|
|
|
The `RestClientBuilder` supports providing both a `RequestConfigCallback` and
|
|
|
|
an `HttpClientConfigCallback` which allow for any customization that the Apache
|
|
|
|
Async Http Client exposes. Those callbacks make it possible to modify some
|
|
|
|
specific behaviour of the client without overriding every other default
|
|
|
|
configuration that the `RestClient` is initialized with. This section
|
|
|
|
describes some common scenarios that require additional configuration for the
|
|
|
|
low-level Java REST Client.
|
|
|
|
|
2017-02-24 07:52:36 -05:00
|
|
|
==== Timeouts
|
2016-07-29 05:22:47 -04:00
|
|
|
|
|
|
|
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
|
|
|
|
https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/config/RequestConfig.Builder.html[`org.apache.http.client.config.RequestConfig.Builder`]
|
|
|
|
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
|
2016-12-05 10:54:51 -05:00
|
|
|
connect timeout (defaults to 1 second) and the socket timeout (defaults to 30
|
|
|
|
seconds). Also we adjust the max retry timeout accordingly (defaults to 30
|
2016-07-29 05:22:47 -04:00
|
|
|
seconds too).
|
|
|
|
|
|
|
|
[source,java]
|
|
|
|
--------------------------------------------------
|
|
|
|
RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200))
|
|
|
|
.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
|
|
|
|
@Override
|
|
|
|
public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
|
|
|
|
return requestConfigBuilder.setConnectTimeout(5000)
|
2016-12-05 10:54:51 -05:00
|
|
|
.setSocketTimeout(60000);
|
2016-07-29 05:22:47 -04:00
|
|
|
}
|
|
|
|
})
|
2016-12-05 10:54:51 -05:00
|
|
|
.setMaxRetryTimeoutMillis(60000)
|
2016-07-29 05:22:47 -04:00
|
|
|
.build();
|
|
|
|
--------------------------------------------------
|
|
|
|
|
2017-02-24 07:52:36 -05:00
|
|
|
==== Number of threads
|
2016-07-29 05:22:47 -04:00
|
|
|
|
|
|
|
The Apache Http Async Client starts by default one dispatcher thread, and a
|
|
|
|
number of worker threads used by the connection manager, as many as the number
|
|
|
|
of locally detected processors (depending on what
|
|
|
|
`Runtime.getRuntime().availableProcessors()` returns). The number of threads
|
|
|
|
can be modified as follows:
|
|
|
|
|
|
|
|
[source,java]
|
|
|
|
--------------------------------------------------
|
|
|
|
RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200))
|
|
|
|
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
|
|
|
|
@Override
|
|
|
|
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
|
|
|
|
return httpClientBuilder.setDefaultIOReactorConfig(
|
|
|
|
IOReactorConfig.custom().setIoThreadCount(1).build());
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.build();
|
|
|
|
--------------------------------------------------
|
|
|
|
|
2017-02-24 07:52:36 -05:00
|
|
|
==== Basic authentication
|
2016-07-29 05:22:47 -04:00
|
|
|
|
|
|
|
Configuring basic authentication can be done by providing an
|
|
|
|
`HttpClientConfigCallback` while building the `RestClient` through its builder.
|
|
|
|
The interface has one method that receives an instance of
|
|
|
|
https://hc.apache.org/httpcomponents-asyncclient-dev/httpasyncclient/apidocs/org/apache/http/impl/nio/client/HttpAsyncClientBuilder.html[`org.apache.http.impl.nio.client.HttpAsyncClientBuilder`]
|
|
|
|
as an argument and has the same return type. The http client builder can be
|
|
|
|
modified and then returned. In the following example we set a default
|
|
|
|
credentials provider that requires basic authentication.
|
|
|
|
|
|
|
|
[source,java]
|
|
|
|
--------------------------------------------------
|
|
|
|
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
|
|
|
credentialsProvider.setCredentials(AuthScope.ANY,
|
|
|
|
new UsernamePasswordCredentials("user", "password"));
|
|
|
|
|
|
|
|
RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200))
|
|
|
|
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
|
|
|
|
@Override
|
|
|
|
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
|
|
|
|
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.build();
|
|
|
|
--------------------------------------------------
|
|
|
|
|
2017-01-24 11:34:05 -05:00
|
|
|
You can disable Preemptive Authentication, which means that every request will be sent without
|
|
|
|
authorization headers to see if it is accepted and, upon receiving a 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`:
|
|
|
|
|
|
|
|
[source,java]
|
|
|
|
--------------------------------------------------
|
|
|
|
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
|
|
|
credentialsProvider.setCredentials(AuthScope.ANY,
|
|
|
|
new UsernamePasswordCredentials("user", "password"));
|
|
|
|
|
|
|
|
RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200))
|
|
|
|
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
|
|
|
|
@Override
|
|
|
|
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
|
|
|
|
// disable preemptive authentication
|
|
|
|
httpClientBuilder.disableAuthCaching();
|
|
|
|
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.build();
|
|
|
|
--------------------------------------------------
|
|
|
|
|
2017-02-24 07:52:36 -05:00
|
|
|
==== Encrypted communication
|
2016-07-29 05:22:47 -04:00
|
|
|
|
|
|
|
Encrypted communication can also be configured through the
|
|
|
|
`HttpClientConfigCallback`. The
|
|
|
|
https://hc.apache.org/httpcomponents-asyncclient-dev/httpasyncclient/apidocs/org/apache/http/impl/nio/client/HttpAsyncClientBuilder.html[`org.apache.http.impl.nio.client.HttpAsyncClientBuilder`]
|
|
|
|
received as an argument exposes multiple methods to configure encrypted
|
|
|
|
communication: `setSSLContext`, `setSSLSessionStrategy` and
|
|
|
|
`setConnectionManager`, in order of precedence from the least important.
|
|
|
|
The following is an example:
|
|
|
|
|
|
|
|
[source,java]
|
|
|
|
--------------------------------------------------
|
Settings: Add infrastructure for elasticsearch keystore
This change is the first towards providing the ability to store
sensitive settings in elasticsearch. It adds the
`elasticsearch-keystore` tool, which allows managing a java keystore.
The keystore is loaded upon node startup in Elasticsearch, and used by
the Setting infrastructure when a setting is configured as secure.
There are a lot of caveats to this PR. The most important is it only
provides the tool and setting infrastructure for secure strings. It does
not yet provide for keystore passwords, keypairs, certificates, or even
convert any existing string settings to secure string settings. Those
will all come in follow up PRs. But this PR was already too big, so this
at least gets a basic version of the infrastructure in.
The two main things to look at. The first is the `SecureSetting` class,
which extends `Setting`, but removes the assumption for the raw value of the
setting to be a string. SecureSetting provides, for now, a single
helper, `stringSetting()` to create a SecureSetting which will return a
SecureString (which is like String, but is closeable, so that the
underlying character array can be cleared). The second is the
`KeyStoreWrapper` class, which wraps the java `KeyStore` to provide a
simpler api (we do not need the entire keystore api) and also extend
the serialized format to add metadata needed for loading the keystore
with no assumptions about keystore type (so that we can change this in
the future) as well as whether the keystore has a password (so that we
can know whether prompting is necessary when we add support for keystore
passwords).
2016-12-22 19:28:34 -05:00
|
|
|
KeyStore keystore = KeyStore.getInstance("jks");
|
2016-07-29 05:22:47 -04:00
|
|
|
try (InputStream is = Files.newInputStream(keyStorePath)) {
|
Settings: Add infrastructure for elasticsearch keystore
This change is the first towards providing the ability to store
sensitive settings in elasticsearch. It adds the
`elasticsearch-keystore` tool, which allows managing a java keystore.
The keystore is loaded upon node startup in Elasticsearch, and used by
the Setting infrastructure when a setting is configured as secure.
There are a lot of caveats to this PR. The most important is it only
provides the tool and setting infrastructure for secure strings. It does
not yet provide for keystore passwords, keypairs, certificates, or even
convert any existing string settings to secure string settings. Those
will all come in follow up PRs. But this PR was already too big, so this
at least gets a basic version of the infrastructure in.
The two main things to look at. The first is the `SecureSetting` class,
which extends `Setting`, but removes the assumption for the raw value of the
setting to be a string. SecureSetting provides, for now, a single
helper, `stringSetting()` to create a SecureSetting which will return a
SecureString (which is like String, but is closeable, so that the
underlying character array can be cleared). The second is the
`KeyStoreWrapper` class, which wraps the java `KeyStore` to provide a
simpler api (we do not need the entire keystore api) and also extend
the serialized format to add metadata needed for loading the keystore
with no assumptions about keystore type (so that we can change this in
the future) as well as whether the keystore has a password (so that we
can know whether prompting is necessary when we add support for keystore
passwords).
2016-12-22 19:28:34 -05:00
|
|
|
keystore.load(is, keyStorePass.toCharArray());
|
2016-07-29 05:22:47 -04:00
|
|
|
}
|
|
|
|
RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200))
|
|
|
|
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
|
|
|
|
@Override
|
|
|
|
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
|
|
|
|
return httpClientBuilder.setSSLContext(sslcontext);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.build();
|
|
|
|
--------------------------------------------------
|
|
|
|
|
2017-02-24 07:52:36 -05:00
|
|
|
==== Others
|
2016-07-29 05:22:47 -04:00
|
|
|
|
|
|
|
For any other required configuration needed, the Apache HttpAsyncClient docs
|
2016-12-05 10:54:51 -05:00
|
|
|
should be consulted: https://hc.apache.org/httpcomponents-asyncclient-4.1.x/ .
|