diff --git a/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpClient.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpClient.java index cdfc94a1e31..f9af31b5e90 100644 --- a/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpClient.java +++ b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpClient.java @@ -7,7 +7,6 @@ package org.elasticsearch.watcher.support.http; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchTimeoutException; -import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.SpecialPermission; import org.elasticsearch.common.Strings; import org.elasticsearch.common.component.AbstractLifecycleComponent; @@ -31,9 +30,8 @@ import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.SocketTimeoutException; -import java.net.URI; -import java.net.URISyntaxException; import java.net.URL; +import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -137,20 +135,18 @@ public class HttpClient extends AbstractLifecycleComponent { if (builder.length() != 0) { builder.append('&'); } - builder.append(entry.getKey()) + builder.append(URLEncoder.encode(entry.getKey(), "UTF-8")) .append('=') - .append(entry.getValue()); + .append(URLEncoder.encode(entry.getValue(), "UTF-8")); } queryString = builder.toString(); } - URI uri; - try { - uri = new URI(request.scheme().scheme(), null, request.host(), request.port(), request.path(), queryString, null); - } catch (URISyntaxException e) { - throw ExceptionsHelper.convertToElastic(e); + String path = request.path; + if (Strings.hasLength(queryString)) { + path += "?" + queryString; } - URL url = uri.toURL(); + URL url = new URL(request.scheme.scheme(), request.host, request.port, path); logger.debug("making [{}] request to [{}]", request.method().method(), url); logger.trace("sending [{}] as body of request", request.body()); diff --git a/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpClientTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpClientTests.java index 22fc3d280e0..7837a92ab38 100644 --- a/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpClientTests.java +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpClientTests.java @@ -35,6 +35,7 @@ import java.security.UnrecoverableKeyException; import static java.util.Collections.singletonMap; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.Is.is; @@ -116,7 +117,7 @@ public class HttpClientTests extends ESTestCase { assertThat(recordedRequest.getBody().readUtf8Line(), nullValue()); } - public void testUrlEncoding() throws Exception{ + public void testUrlEncodingWithQueryStrings() throws Exception{ webServer.enqueue(new MockResponse().setResponseCode(200).setBody("body")); HttpRequest.Builder requestBuilder = HttpRequest.builder("localhost", webPort) .method(HttpMethod.GET) @@ -128,7 +129,7 @@ public class HttpClientTests extends ESTestCase { assertThat(response.body().toUtf8(), equalTo("body")); RecordedRequest recordedRequest = webServer.takeRequest(); - assertThat(recordedRequest.getPath(), equalTo("/test?key=value%20123:123")); + assertThat(recordedRequest.getPath(), equalTo("/test?key=value+123%3A123")); assertThat(recordedRequest.getBody().readUtf8Line(), nullValue()); } @@ -358,6 +359,21 @@ public class HttpClientTests extends ESTestCase { } } + public void testThatUrlPathIsNotEncoded() throws Exception { + // %2F is a slash that needs to be encoded to not be misinterpreted as a path + String path = "//_search"; + webServer.enqueue(new MockResponse().setResponseCode(200).setBody("foo")); + HttpRequest request = HttpRequest.builder("localhost", webServer.getPort()).path(path).build(); + httpClient.execute(request); + + assertThat(webServer.getRequestCount(), is(1)); + + RecordedRequest recordedRequest = webServer.takeRequest(); + // under no circumstances have a double encode of %2F => %25 (percent sign) + assertThat(recordedRequest.getPath(), not(containsString("%25"))); + assertThat(recordedRequest.getPath(), equalTo(path)); + } + private MockWebServer startWebServer(int startPort, int endPort) throws IOException { for (int port = startPort; port < endPort; port++) { try {