DATAES-705_-_Add-support-for-PathPrefix-to-clients-in-3_2_x.

Original PR: #354
This commit is contained in:
Peter-Josef Meisch 2019-12-07 15:42:09 +01:00 committed by GitHub
parent 325fdb47c6
commit 0a0ac102cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 136 additions and 24 deletions

View File

@ -31,6 +31,7 @@ import org.springframework.http.HttpHeaders;
*
* @author Mark Paluch
* @author Peter-Josef Meisch
* @author Huw Ayling-Miller
* @author Henrique Amaral
* @since 3.2
*/
@ -144,11 +145,19 @@ public interface ClientConfiguration {
*/
Duration getSocketTimeout();
/**
* Returns the path prefix that should be prepended to HTTP(s) requests for Elasticsearch behind a proxy.
*
* @return the path prefix.
* @since 3.2.4
*/
String getPathPrefix();
/**
* returns an optionally set proxy in the form host:port
*
* @return the optional proxy
* @since 4.0
* @since 3.2.4
*/
Optional<String> getProxy();
@ -294,6 +303,15 @@ public interface ClientConfiguration {
*/
TerminalClientConfigurationBuilder withBasicAuth(String username, String password);
/**
* Configure the path prefix that will be prepended to any HTTP(s) requests
*
* @param pathPrefix the pathPrefix.
* @return the {@link TerminalClientConfigurationBuilder}
* @since 3.2.4
*/
TerminalClientConfigurationBuilder withPathPrefix(String pathPrefix);
/**
* @param proxy a proxy formatted as String {@literal host:port}.
* @return the {@link MaybeSecureClientConfigurationBuilder}.

View File

@ -38,6 +38,7 @@ import org.springframework.util.Assert;
* @author Christoph Strobl
* @author Mark Paluch
* @author Peter-Josef Meisch
* @author Huw Ayling-Miller
* @author Henrique Amaral
* @since 3.2
*/
@ -53,7 +54,8 @@ class ClientConfigurationBuilder
private Duration soTimeout = Duration.ofSeconds(5);
private String username;
private String password;
private String proxy;
private String pathPrefix;
private String proxy;
/*
* (non-Javadoc)
@ -183,6 +185,14 @@ class ClientConfigurationBuilder
return this;
}
@Override
public TerminalClientConfigurationBuilder withPathPrefix(String pathPrefix) {
this.pathPrefix = pathPrefix;
return this;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationBuilderWithOptionalDefaultHeaders#build()
@ -197,7 +207,7 @@ class ClientConfigurationBuilder
headers.setBasicAuth(username, password);
}
return new DefaultClientConfiguration(hosts, headers, useSsl, sslContext, soTimeout, connectTimeout,
return new DefaultClientConfiguration(hosts, headers, useSsl, sslContext, soTimeout, connectTimeout, pathPrefix,
hostnameVerifier, proxy);
}

View File

@ -33,6 +33,8 @@ import org.springframework.lang.Nullable;
*
* @author Mark Paluch
* @author Christoph Strobl
* @author Huw Ayling-Miller
* @author Peter-Josef Meisch
* @since 3.2
*/
class DefaultClientConfiguration implements ClientConfiguration {
@ -43,11 +45,12 @@ class DefaultClientConfiguration implements ClientConfiguration {
private final @Nullable SSLContext sslContext;
private final Duration soTimeout;
private final Duration connectTimeout;
private final String pathPrefix;
private final @Nullable HostnameVerifier hostnameVerifier;
private final String proxy;
DefaultClientConfiguration(List<InetSocketAddress> hosts, HttpHeaders headers, boolean useSsl,
@Nullable SSLContext sslContext, Duration soTimeout, Duration connectTimeout,
@Nullable SSLContext sslContext, Duration soTimeout, Duration connectTimeout, @Nullable String pathPrefix,
@Nullable HostnameVerifier hostnameVerifier, String proxy) {
this.hosts = Collections.unmodifiableList(new ArrayList<>(hosts));
@ -56,6 +59,7 @@ class DefaultClientConfiguration implements ClientConfiguration {
this.sslContext = sslContext;
this.soTimeout = soTimeout;
this.connectTimeout = connectTimeout;
this.pathPrefix = pathPrefix;
this.hostnameVerifier = hostnameVerifier;
this.proxy = proxy;
}
@ -123,12 +127,21 @@ class DefaultClientConfiguration implements ClientConfiguration {
return this.soTimeout;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.ClientConfiguration#getProxy()
*/
@Override
public Optional<String> getProxy() {
return Optional.ofNullable(proxy);
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.ClientConfiguration#getPathPrefix()
*/
@Override
public String getPathPrefix() {
return this.pathPrefix;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.ClientConfiguration#getProxy()
*/
@Override
public Optional<String> getProxy() {
return Optional.ofNullable(proxy);
}
}

View File

@ -53,7 +53,9 @@ import org.springframework.util.Assert;
*
* @author Christoph Strobl
* @author Mark Paluch
* @author Huw Ayling-Miller
* @author Henrique Amaral
* @author Peter-Josef Meisch
* @since 3.2
*/
public final class RestClients {
@ -77,6 +79,11 @@ public final class RestClients {
HttpHost[] httpHosts = formattedHosts(clientConfiguration.getEndpoints(), clientConfiguration.useSsl()).stream()
.map(HttpHost::create).toArray(HttpHost[]::new);
RestClientBuilder builder = RestClient.builder(httpHosts);
if (clientConfiguration.getPathPrefix() != null) {
builder.setPathPrefix(clientConfiguration.getPathPrefix());
}
HttpHeaders headers = clientConfiguration.getDefaultHeaders();
if (!headers.isEmpty()) {

View File

@ -125,6 +125,8 @@ import org.springframework.web.reactive.function.client.WebClient.RequestBodySpe
*
* @author Christoph Strobl
* @author Mark Paluch
* @author Peter-Josef Meisch
* @author Huw Ayling-Miller
* @author Henrique Amaral
* @since 3.2
* @see ClientConfiguration
@ -220,6 +222,10 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
WebClientProvider provider = WebClientProvider.create(scheme, connector);
if (clientConfiguration.getPathPrefix() != null) {
provider = provider.withPathPrefix(clientConfiguration.getPathPrefix());
}
return provider.withDefaultHeaders(clientConfiguration.getDefaultHeaders());
}

View File

@ -32,6 +32,8 @@ import org.springframework.web.reactive.function.client.WebClient.Builder;
*
* @author Mark Paluch
* @author Christoph Strobl
* @author Huw Ayling-Miller
* @author Peter-Josef Meisch
* @since 3.2
*/
class DefaultWebClientProvider implements WebClientProvider {
@ -42,6 +44,7 @@ class DefaultWebClientProvider implements WebClientProvider {
private final @Nullable ClientHttpConnector connector;
private final Consumer<Throwable> errorListener;
private final HttpHeaders headers;
private final String pathPrefix;
/**
* Create new {@link DefaultWebClientProvider} with empty {@link HttpHeaders} and no-op {@literal error listener}.
@ -50,19 +53,20 @@ class DefaultWebClientProvider implements WebClientProvider {
* @param connector can be {@literal null}.
*/
DefaultWebClientProvider(String scheme, @Nullable ClientHttpConnector connector) {
this(scheme, connector, e -> {}, HttpHeaders.EMPTY);
this(scheme, connector, e -> {}, HttpHeaders.EMPTY, null);
}
/**
* Create new {@link DefaultWebClientProvider} with empty {@link HttpHeaders} and no-op {@literal error listener}.
*
*
* @param scheme must not be {@literal null}.
* @param connector can be {@literal null}.
* @param errorListener must not be {@literal null}.
* @param headers must not be {@literal null}.
* @param pathPrefixcan be {@literal null}
*/
private DefaultWebClientProvider(String scheme, @Nullable ClientHttpConnector connector,
Consumer<Throwable> errorListener, HttpHeaders headers) {
Consumer<Throwable> errorListener, HttpHeaders headers, @Nullable String pathPrefix) {
Assert.notNull(scheme, "Scheme must not be null! A common scheme would be 'http'.");
Assert.notNull(errorListener, "ErrorListener must not be null! You may want use a no-op one 'e -> {}' instead.");
@ -73,6 +77,7 @@ class DefaultWebClientProvider implements WebClientProvider {
this.connector = connector;
this.errorListener = errorListener;
this.headers = headers;
this.pathPrefix = pathPrefix;
}
/*
@ -109,7 +114,7 @@ class DefaultWebClientProvider implements WebClientProvider {
merged.addAll(this.headers);
merged.addAll(headers);
return new DefaultWebClientProvider(this.scheme, this.connector, errorListener, merged);
return new DefaultWebClientProvider(this.scheme, this.connector, errorListener, merged, this.pathPrefix);
}
/*
@ -121,6 +126,15 @@ class DefaultWebClientProvider implements WebClientProvider {
return this.errorListener;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.WebClientProvider#getPathPrefix()
*/
@Override
public String getPathPrefix() {
return pathPrefix;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.WebClientProvider#withErrorListener(java.util.function.Consumer)
@ -131,7 +145,18 @@ class DefaultWebClientProvider implements WebClientProvider {
Assert.notNull(errorListener, "Error listener must not be null.");
Consumer<Throwable> listener = this.errorListener.andThen(errorListener);
return new DefaultWebClientProvider(this.scheme, this.connector, listener, this.headers);
return new DefaultWebClientProvider(this.scheme, this.connector, listener, this.headers, this.pathPrefix);
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.client.reactive.WebClientProvider#withPathPrefix(java.lang.String)
*/
@Override
public WebClientProvider withPathPrefix(String pathPrefix) {
Assert.notNull(pathPrefix, "pathPrefix must not be null.");
return new DefaultWebClientProvider(this.scheme, this.connector, this.errorListener, this.headers, pathPrefix);
}
protected WebClient createWebClientForSocketAddress(InetSocketAddress socketAddress) {
@ -142,7 +167,8 @@ class DefaultWebClientProvider implements WebClientProvider {
builder = builder.clientConnector(connector);
}
String baseUrl = String.format("%s://%s:%d", this.scheme, socketAddress.getHostString(), socketAddress.getPort());
String baseUrl = String.format("%s://%s:%d%s", this.scheme, socketAddress.getHostString(), socketAddress.getPort(),
pathPrefix == null ? "" : "/" + pathPrefix);
return builder.baseUrl(baseUrl).filter((request, next) -> next.exchange(request).doOnError(errorListener)).build();
}
}

View File

@ -48,7 +48,6 @@ import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.search.SearchHit;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.ElasticsearchHost;
import org.springframework.http.HttpHeaders;
@ -341,7 +340,7 @@ public interface ReactiveElasticsearchClient {
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-count.html">Count API on
* elastic.co</a>
* @return the {@link Mono} emitting the count result.
* @since 4.0
* @since 3.2.4
*/
default Mono<Long> count(Consumer<CountRequest> consumer) {
@ -357,7 +356,7 @@ public interface ReactiveElasticsearchClient {
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-count.html">Count API on
* elastic.co</a>
* @return the {@link Mono} emitting the count result.
* @since 4.0
* @since 3.2.4
*/
default Mono<Long> count(CountRequest countRequest) {
return count(HttpHeaders.EMPTY, countRequest);
@ -371,7 +370,7 @@ public interface ReactiveElasticsearchClient {
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-count.html">Count API on
* elastic.co</a>
* @return the {@link Mono} emitting the count result.
* @since 4.0
* @since 3.2.4
*/
Mono<Long> count(HttpHeaders headers, CountRequest countRequest);

View File

@ -34,6 +34,8 @@ import org.springframework.web.reactive.function.client.WebClient;
*
* @author Christoph Strobl
* @author Mark Paluch
* @author Huw Ayling-Miller
* @author Peter-Josef Meisch
* @since 3.2
*/
public interface WebClientProvider {
@ -96,6 +98,14 @@ public interface WebClientProvider {
*/
Consumer<Throwable> getErrorListener();
/**
* Obtain the {@link String pathPrefix} to be used.
*
* @return the pathPrefix if set.
* @since 3.2.4
*/
String getPathPrefix();
/**
* Create a new instance of {@link WebClientProvider} applying the given headers by default.
*
@ -111,4 +121,13 @@ public interface WebClientProvider {
* @return new instance of {@link WebClientProvider}.
*/
WebClientProvider withErrorListener(Consumer<Throwable> errorListener);
/**
* Create a new instance of {@link WebClientProvider} where HTTP requests are called with the given path prefix.
*
* @param pathPrefix Path prefix to add to requests
* @return new instance of {@link WebClientProvider}
* @since 3.2.4
*/
WebClientProvider withPathPrefix(String pathPrefix);
}

View File

@ -394,7 +394,7 @@ public class RequestConverters {
*
* @param countRequest the search defining the data to be counted
* @return Elasticsearch count request
* @since 4.0
* @since 3.2
*/
public static Request count(CountRequest countRequest) {
Request request = new Request(HttpMethod.POST.name(),

View File

@ -32,6 +32,7 @@ import org.springframework.http.HttpHeaders;
*
* @author Mark Paluch
* @author Peter-Josef Meisch
* @author Huw Ayling-Miller
* @author Henrique Amaral
*/
public class ClientConfigurationUnitTests {
@ -55,6 +56,7 @@ public class ClientConfigurationUnitTests {
.usingSsl() //
.withDefaultHeaders(headers) //
.withConnectTimeout(Duration.ofDays(1)).withSocketTimeout(Duration.ofDays(2)) //
.withPathPrefix("myPathPrefix") //
.withProxy("localhost:8080").build();
assertThat(clientConfiguration.getEndpoints()).containsOnly(InetSocketAddress.createUnresolved("foo", 9200),
@ -63,6 +65,7 @@ public class ClientConfigurationUnitTests {
assertThat(clientConfiguration.getDefaultHeaders().get("foo")).containsOnly("bar");
assertThat(clientConfiguration.getConnectTimeout()).isEqualTo(Duration.ofDays(1));
assertThat(clientConfiguration.getSocketTimeout()).isEqualTo(Duration.ofDays(2));
assertThat(clientConfiguration.getPathPrefix()).isEqualTo("myPathPrefix");
assertThat(clientConfiguration.getProxy()).contains("localhost:8080");
}

View File

@ -39,7 +39,6 @@ import java.util.function.Supplier;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.data.elasticsearch.client.ElasticsearchHost;
@ -60,7 +59,9 @@ import org.springframework.web.util.UriBuilder;
/**
* @author Christoph Strobl
* @author Huw Ayling-Miller
* @author Henrique Amaral
* @author Peter-Josef Meisch
*/
public class ReactiveMockClientTestsUtils {
@ -266,6 +267,16 @@ public class ReactiveMockClientTestsUtils {
throw new UnsupportedOperationException();
}
@Override
public String getPathPrefix() {
return null;
}
@Override
public WebClientProvider withPathPrefix(String pathPrefix) {
throw new UnsupportedOperationException();
}
public Send when(String host) {
InetSocketAddress inetSocketAddress = getInetSocketAddress(host);
return new CallbackImpl(get(host), headersUriSpecMap.get(inetSocketAddress),