diff --git a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/JreHttpUrlConnection.java b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/JreHttpUrlConnection.java index 716b1bb058a..1e3f2d95ae2 100644 --- a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/JreHttpUrlConnection.java +++ b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/JreHttpUrlConnection.java @@ -35,6 +35,7 @@ import javax.net.ssl.SSLSocketFactory; import javax.sql.rowset.serial.SerialException; import static java.util.Collections.emptyMap; +import static org.elasticsearch.xpack.sql.client.UriUtils.appendSegmentToPath; import static org.elasticsearch.xpack.sql.proto.Protocol.SQL_QUERY_REST_ENDPOINT; /** @@ -52,7 +53,7 @@ public class JreHttpUrlConnection implements Closeable { + "?error_trace] and method [POST], allowed:"; public static R http(String path, String query, ConnectionConfiguration cfg, Function handler) { - final URI uriPath = cfg.baseUri().resolve(path); // update path if needed + final URI uriPath = appendSegmentToPath(cfg.baseUri(), path); // update path if needed final String uriQuery = query == null ? uriPath.getQuery() : query; // update query if needed final URL url; try { diff --git a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/UriUtils.java b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/UriUtils.java index 26113010c61..4f07e15df87 100644 --- a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/UriUtils.java +++ b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/UriUtils.java @@ -76,4 +76,33 @@ public final class UriUtils { throw new IllegalArgumentException("Invalid connection configuration [" + connectionString + "]: " + e.getMessage(), e); } } + + public static URI appendSegmentToPath(URI uri, String segment) { + if (uri == null) { + throw new IllegalArgumentException("URI must not be null"); + } + if (segment == null || segment.isEmpty() || "/".equals(segment)) { + return uri; + } + + String path = uri.getPath(); + String concatenatedPath = ""; + String cleanSegment = segment.startsWith("/") ? segment.substring(1) : segment; + + if (path == null || path.isEmpty()) { + path = "/"; + } + + if (path.charAt(path.length() - 1) == '/') { + concatenatedPath = path + cleanSegment; + } else { + concatenatedPath = path + "/" + cleanSegment; + } + try { + return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), concatenatedPath, + uri.getQuery(), uri.getFragment()); + } catch (URISyntaxException e) { + throw new IllegalArgumentException("Invalid segment [" + segment + "] for URI [" + uri + "]: " + e.getMessage(), e); + } + } } diff --git a/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/UriUtilsTests.java b/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/UriUtilsTests.java index 0b7f6c47b0d..c710a7574e4 100644 --- a/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/UriUtilsTests.java +++ b/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/UriUtilsTests.java @@ -9,6 +9,7 @@ import org.elasticsearch.test.ESTestCase; import java.net.URI; +import static org.elasticsearch.xpack.sql.client.UriUtils.appendSegmentToPath; import static org.elasticsearch.xpack.sql.client.UriUtils.parseURI; import static org.elasticsearch.xpack.sql.client.UriUtils.removeQuery; @@ -84,4 +85,56 @@ public class UriUtilsTests extends ESTestCase { assertEquals(URI.create("http://server:9100"), removeQuery(URI.create("http://server:9100"), "http://server:9100", DEFAULT_URI)); } + + public void testAppendEmptySegmentToPath() throws Exception { + assertEquals(URI.create("http://server:9100"), + appendSegmentToPath(URI.create("http://server:9100"), "")); + } + + public void testAppendNullSegmentToPath() throws Exception { + assertEquals(URI.create("http://server:9100"), + appendSegmentToPath(URI.create("http://server:9100"), null)); + } + + public void testAppendSegmentToNullPath() throws Exception { + assertEquals( + "URI must not be null", + expectThrows(IllegalArgumentException.class, () -> appendSegmentToPath(null, "/_sql")).getMessage() + ); + } + + public void testAppendSegmentToEmptyPath() throws Exception { + assertEquals(URI.create("/_sql"), + appendSegmentToPath(URI.create(""), "/_sql")); + } + + public void testAppendSlashSegmentToPath() throws Exception { + assertEquals(URI.create("http://server:9100"), + appendSegmentToPath(URI.create("http://server:9100"), "/")); + } + + public void testAppendSqlSegmentToPath() throws Exception { + assertEquals(URI.create("http://server:9100/_sql"), + appendSegmentToPath(URI.create("http://server:9100"), "/_sql")); + } + + public void testAppendSqlSegmentNoSlashToPath() throws Exception { + assertEquals(URI.create("http://server:9100/_sql"), + appendSegmentToPath(URI.create("http://server:9100"), "_sql")); + } + + public void testAppendSegmentToPath() throws Exception { + assertEquals(URI.create("http://server:9100/es_rest/_sql"), + appendSegmentToPath(URI.create("http://server:9100/es_rest"), "/_sql")); + } + + public void testAppendSegmentNoSlashToPath() throws Exception { + assertEquals(URI.create("http://server:9100/es_rest/_sql"), + appendSegmentToPath(URI.create("http://server:9100/es_rest"), "_sql")); + } + + public void testAppendSegmentTwoSlashesToPath() throws Exception { + assertEquals(URI.create("https://server:9100/es_rest/_sql"), + appendSegmentToPath(URI.create("https://server:9100/es_rest/"), "/_sql")); + } }