Skip to content

Commit 60c6312

Browse files
Handle path prefixes when creating clients using URIs (#979) (#981)
Co-authored-by: Sylvain Wallez <sylvain@elastic.co>
1 parent d7f98ef commit 60c6312

File tree

4 files changed

+88
-7
lines changed

4 files changed

+88
-7
lines changed

java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java

+16-6
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,7 @@ public class Rest5Client implements Closeable {
155155
* Creates a new builder instance and sets the hosts that the client will send requests to.
156156
*/
157157
public static Rest5ClientBuilder builder(URI... uris) {
158-
if (uris == null || uris.length == 0) {
159-
throw new IllegalArgumentException("uris must not be null nor empty");
160-
}
161-
List<Node> nodes = Arrays.stream(uris).map(u -> new Node(HttpHost.create(u))).toList();
162-
return new Rest5ClientBuilder(nodes);
158+
return builder(Arrays.asList(uris));
163159
}
164160

165161
/**
@@ -170,13 +166,27 @@ public static Rest5ClientBuilder builder(List<URI> uris) {
170166
if (uris == null || uris.isEmpty()) {
171167
throw new IllegalArgumentException("uris must not be null nor empty");
172168
}
169+
String prefix = uris.get(0).getPath();
170+
173171
List<Node> nodes = uris.stream().map(u -> {
174172
if (!u.isAbsolute()) {
175173
throw new IllegalArgumentException("Expecting an absolute url: [" + u + "]");
176174
}
175+
if (!Objects.equals(u.getPath(), prefix)) {
176+
throw new IllegalArgumentException(
177+
"All hosts must have the same URL path (" +
178+
uris.get(0) + " and " + u + ")"
179+
);
180+
}
177181
return new Node(HttpHost.create(u));
178182
}).toList();
179-
return new Rest5ClientBuilder(nodes);
183+
184+
Rest5ClientBuilder result = new Rest5ClientBuilder(nodes);
185+
186+
if (prefix != null && !prefix.isEmpty()) {
187+
result.setPathPrefix(prefix);
188+
}
189+
return result;
180190
}
181191

182192
/**

java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java

+18-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
import javax.annotation.Nullable;
3333
import java.util.Base64;
34+
import java.util.Objects;
3435

3536
public class RestClientTransport extends ElasticsearchTransportBase {
3637

@@ -61,9 +62,25 @@ public RestClientTransport(RestClient restClient, JsonpMapper jsonpMapper, RestC
6162

6263
private static RestClient buildRestClient(ElasticsearchTransportConfig config) {
6364
RestClientBuilder restClientBuilder = RestClient.builder(config.hosts().stream()
64-
.map(h -> HttpHost.create(h.toString())).toArray(HttpHost[]::new)
65+
.map(h -> new HttpHost(h.getHost(), h.getPort(), h.getScheme())).toArray(HttpHost[]::new)
6566
);
6667

68+
String prefix = config.hosts().get(0).getPath();
69+
if (config.hosts().size() > 1) {
70+
for (var host : config.hosts()) {
71+
if (!Objects.equals(host.getPath(), prefix)) {
72+
throw new IllegalArgumentException(
73+
"All hosts must have the same URL path (" +
74+
config.hosts().get(0) + " and " + host + ")"
75+
);
76+
}
77+
}
78+
}
79+
80+
if (prefix != null && !prefix.isEmpty()) {
81+
restClientBuilder.setPathPrefix(prefix);
82+
}
83+
6784
if (config.username() != null && config.password() != null) {
6885
var cred = Base64.getEncoder().encodeToString((config.username() + ":" + config.password()).getBytes());
6986
restClientBuilder.setDefaultHeaders(new org.apache.http.Header[]{

java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestClient.java

+5
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,9 @@ public static ElasticsearchClient createClient(HttpServer server, @Nullable Json
7373
var address = server.getAddress();
7474
return createClient("http://" + address.getHostString() + ":" + address.getPort(), mapper, null);
7575
}
76+
77+
public static Function<ElasticsearchTransportConfig, ElasticsearchTransport> transportFactory() {
78+
System.out.println("Using a " + flavor + " client");
79+
return flavor.transportFactory();
80+
}
7681
}

java-client/src/test/java/co/elastic/clients/transport/ElasticsearchTransportConfigTest.java

+49
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,22 @@
2020
package co.elastic.clients.transport;
2121

2222
import co.elastic.clients.elasticsearch.ElasticsearchClient;
23+
import co.elastic.clients.elasticsearch.ElasticsearchTestClient;
24+
import co.elastic.clients.elasticsearch.indices.GetAliasResponse;
2325
import co.elastic.clients.transport.rest5_client.Rest5ClientOptions;
2426
import co.elastic.clients.transport.rest5_client.Rest5ClientTransport;
2527
import co.elastic.clients.transport.rest_client.RestClientOptions;
2628
import co.elastic.clients.transport.rest_client.RestClientTransport;
29+
import com.sun.net.httpserver.HttpServer;
2730
import org.elasticsearch.client.RequestOptions;
2831
import org.junit.jupiter.api.Assertions;
2932
import org.junit.jupiter.api.Test;
3033

34+
import java.io.IOException;
35+
import java.net.InetAddress;
36+
import java.net.InetSocketAddress;
37+
import java.nio.charset.StandardCharsets;
38+
3139
public class ElasticsearchTransportConfigTest extends Assertions {
3240

3341
@Test
@@ -132,4 +140,45 @@ public void checkDefaultConfig() throws Exception {
132140
assertInstanceOf(Rest5ClientTransport.class, transport);
133141
}
134142
}
143+
144+
@Test
145+
public void testPathPrefix() throws IOException {
146+
HttpServer server = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0);
147+
148+
server.createContext("/path-prefix/_alias", exchange -> {
149+
exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch");
150+
exchange.getResponseHeaders().set("Content-Type", "application/json");
151+
exchange.sendResponseHeaders(200, 0);
152+
153+
exchange.getResponseBody().write("{\"foo\":{\"aliases\":{}}}".getBytes(StandardCharsets.UTF_8));
154+
exchange.close();
155+
});
156+
157+
server.start();
158+
159+
var address = server.getAddress();
160+
var url = "http://" + address.getHostName() + ":" + address.getPort() + "/path-prefix";
161+
162+
// No trailing slash
163+
try(var esClient = ElasticsearchClient.of(b -> b
164+
.host(url)
165+
.transportFactory(ElasticsearchTestClient.transportFactory())
166+
)) {
167+
GetAliasResponse alias = esClient.indices().getAlias();
168+
assertEquals(1, alias.aliases().size());
169+
assertNotNull(alias.aliases().get("foo"));
170+
}
171+
172+
// Trailing slash
173+
try(var esClient = ElasticsearchClient.of(b -> b
174+
.host(url + "/")
175+
.transportFactory(ElasticsearchTestClient.transportFactory())
176+
)) {
177+
GetAliasResponse alias = esClient.indices().getAlias();
178+
assertEquals(1, alias.aliases().size());
179+
assertNotNull(alias.aliases().get("foo"));
180+
}
181+
182+
server.stop(0);
183+
}
135184
}

0 commit comments

Comments
 (0)