Tests: Remove HttpClient to only use one Http client

The HTTP client implementation used by the Elasticsearch REST tests is
backed by apache http client instead of a self written helper class,
that uses HttpUrlConnection. This commit removes the old simple HttpClient
class and uses the more powerful and reliable one for all tests.

It also fixes a minor bug, that when sending a 301 redirect, a Location
header needs to be added as well, which was uncovered by the switching
to the new client.

Closes #7003
This commit is contained in:
Alexander Reelsen 2014-07-25 10:26:52 +02:00
parent 51fd2f513c
commit 35e562343f
10 changed files with 138 additions and 280 deletions

View File

@ -154,7 +154,10 @@ public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
pluginName = path; pluginName = path;
sitePath = null; sitePath = null;
// If a trailing / is missing, we redirect to the right page #2654 // If a trailing / is missing, we redirect to the right page #2654
channel.sendResponse(new BytesRestResponse(RestStatus.MOVED_PERMANENTLY, "text/html", "<head><meta http-equiv=\"refresh\" content=\"0; URL=" + request.rawPath() + "/\"></head>")); String redirectUrl = request.rawPath() + "/";
BytesRestResponse restResponse = new BytesRestResponse(RestStatus.MOVED_PERMANENTLY, "text/html", "<head><meta http-equiv=\"refresh\" content=\"0; URL=" + redirectUrl + "></head>");
restResponse.addHeader("Location", redirectUrl);
channel.sendResponse(restResponse);
return; return;
} else { } else {
pluginName = path.substring(0, i1); pluginName = path.substring(0, i1);

View File

@ -19,15 +19,16 @@
package org.elasticsearch.options.jsonp; package org.elasticsearch.options.jsonp;
import org.apache.http.impl.client.HttpClients;
import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.http.HttpServerTransport; import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.helper.HttpClient;
import org.elasticsearch.rest.helper.HttpClientResponse;
import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import org.elasticsearch.test.ElasticsearchIntegrationTest.Scope; import org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
import org.elasticsearch.test.rest.client.http.HttpRequestBuilder;
import org.elasticsearch.test.rest.client.http.HttpResponse;
import org.junit.Test; import org.junit.Test;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
@ -55,11 +56,12 @@ public class JsonpOptionDisabledTest extends ElasticsearchIntegrationTest {
@Test @Test
public void testThatJSONPisDisabled() throws Exception { public void testThatJSONPisDisabled() throws Exception {
// Make the HTTP request // Make the HTTP request
HttpServerTransport httpServerTransport = internalCluster().getDataNodeInstance(HttpServerTransport.class); HttpResponse response = new HttpRequestBuilder(HttpClients.createDefault()).httpTransport(internalCluster().getDataNodeInstance(HttpServerTransport.class))
HttpClient httpClient = new HttpClient(httpServerTransport.boundAddress().publishAddress()); .path("/")
HttpClientResponse response = httpClient.request("/?callback=DisabledJSONPCallback"); .addParam("callback", "DisabledJSONPCallback").execute();
assertThat(response.getHeader("Content-Type"), is("application/javascript"));
assertThat(response.response(), containsString("DisabledJSONPCallback(")); assertThat(response.getHeaders().get("Content-Type"), is("application/javascript"));
assertThat(response.response(), containsString("JSONP is disabled")); assertThat(response.getBody(), containsString("DisabledJSONPCallback("));
assertThat(response.getBody(), containsString("JSONP is disabled"));
} }
} }

View File

@ -19,15 +19,16 @@
package org.elasticsearch.options.jsonp; package org.elasticsearch.options.jsonp;
import org.apache.http.impl.client.HttpClients;
import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.http.HttpServerTransport; import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.helper.HttpClient;
import org.elasticsearch.rest.helper.HttpClientResponse;
import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import org.elasticsearch.test.ElasticsearchIntegrationTest.Scope; import org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
import org.elasticsearch.test.rest.client.http.HttpRequestBuilder;
import org.elasticsearch.test.rest.client.http.HttpResponse;
import org.junit.Test; import org.junit.Test;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
@ -50,11 +51,9 @@ public class JsonpOptionEnabledTest extends ElasticsearchIntegrationTest {
@Test @Test
public void testThatJSONPisEnabled() throws Exception { public void testThatJSONPisEnabled() throws Exception {
// Make the HTTP request // Make the HTTP request
HttpServerTransport httpServerTransport = internalCluster().getDataNodeInstance(HttpServerTransport.class); HttpResponse response = new HttpRequestBuilder(HttpClients.createDefault()).httpTransport(internalCluster().getDataNodeInstance(HttpServerTransport.class)).path("/").addParam("callback", "EnabledJSONPCallback").execute();
HttpClient httpClient = new HttpClient(httpServerTransport.boundAddress().publishAddress()); assertThat(response.getHeaders().get("Content-Type"), is("application/javascript"));
HttpClientResponse response = httpClient.request("/?callback=EnabledJSONPCallback"); assertThat(response.getBody(), containsString("EnabledJSONPCallback("));
assertThat(response.getHeader("Content-Type"), is("application/javascript")); assertThat(response.getBody(), containsString("You Know, for Search"));
assertThat(response.response(), containsString("EnabledJSONPCallback("));
assertThat(response.response(), containsString("You Know, for Search"));
} }
} }

View File

@ -19,6 +19,8 @@
package org.elasticsearch.plugin; package org.elasticsearch.plugin;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import org.apache.http.impl.client.HttpClients;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchIllegalArgumentException; import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.ElasticsearchTimeoutException; import org.elasticsearch.ElasticsearchTimeoutException;
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse; import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
@ -33,11 +35,11 @@ import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.elasticsearch.node.internal.InternalSettingsPreparer;
import org.elasticsearch.plugins.PluginManager; import org.elasticsearch.plugins.PluginManager;
import org.elasticsearch.rest.RestStatus; import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.helper.HttpClient;
import org.elasticsearch.rest.helper.HttpClientResponse;
import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import org.elasticsearch.test.junit.annotations.Network; import org.elasticsearch.test.junit.annotations.Network;
import org.elasticsearch.test.rest.client.http.HttpRequestBuilder;
import org.elasticsearch.test.rest.client.http.HttpResponse;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -205,31 +207,37 @@ public class PluginManagerTests extends ElasticsearchIntegrationTest {
assertThat(pluginFound, is(true)); assertThat(pluginFound, is(true));
} }
private void assertPluginAvailable(String pluginName) throws InterruptedException { private void assertPluginAvailable(String pluginName) throws InterruptedException, IOException {
HttpServerTransport httpServerTransport = internalCluster().getInstance(HttpServerTransport.class); final HttpRequestBuilder httpRequestBuilder = getHttpRequestBuilder();
final HttpClient httpClient = new HttpClient(httpServerTransport.boundAddress().publishAddress());
logger.info("--> tested http address [{}]", httpServerTransport.info().getAddress());
//checking that the http connector is working properly //checking that the http connector is working properly
// We will try it for some seconds as it could happen that the REST interface is not yet fully started // We will try it for some seconds as it could happen that the REST interface is not yet fully started
assertThat(awaitBusy(new Predicate<Object>() { assertThat(awaitBusy(new Predicate<Object>() {
public boolean apply(Object obj) { public boolean apply(Object obj) {
HttpClientResponse response = httpClient.request(""); try {
if (response.errorCode() != RestStatus.OK.getStatus()) { HttpResponse response = httpRequestBuilder.method("GET").path("/").execute();
// We want to trace what's going on here before failing the test if (response.getStatusCode() != RestStatus.OK.getStatus()) {
logger.info("--> error caught [{}], headers [{}]", response.errorCode(), response.getHeaders()); // We want to trace what's going on here before failing the test
logger.info("--> cluster state [{}]", internalCluster().clusterService().state()); logger.info("--> error caught [{}], headers [{}]", response.getStatusCode(), response.getHeaders());
return false; logger.info("--> cluster state [{}]", internalCluster().clusterService().state());
return false;
}
return true;
} catch (IOException e) {
throw new ElasticsearchException("HTTP problem", e);
} }
return true;
} }
}, 5, TimeUnit.SECONDS), equalTo(true)); }, 5, TimeUnit.SECONDS), equalTo(true));
//checking now that the plugin is available //checking now that the plugin is available
HttpClientResponse response = httpClient.request("_plugin/" + pluginName + "/"); HttpResponse response = getHttpRequestBuilder().method("GET").path("/_plugin/" + pluginName + "/").execute();
assertThat(response, notNullValue()); assertThat(response, notNullValue());
assertThat(response.errorCode(), equalTo(RestStatus.OK.getStatus())); assertThat(response.getStatusCode(), equalTo(RestStatus.OK.getStatus()));
}
private HttpRequestBuilder getHttpRequestBuilder() {
return new HttpRequestBuilder(HttpClients.createDefault()).httpTransport(internalCluster().getDataNodeInstance(HttpServerTransport.class));
} }
@Test @Test
@ -300,7 +308,7 @@ public class PluginManagerTests extends ElasticsearchIntegrationTest {
@Test @Test
@Network @Network
public void testInstallPluginWithElasticsearchDownloadService() throws IOException { public void testInstallPluginWithElasticsearchDownloadService() throws IOException {
assumeTrue(isDownloadServiceWorking("http://download.elasticsearch.org/", "elasticsearch/ci-test.txt")); assumeTrue(isDownloadServiceWorking("download.elasticsearch.org", 80, "/elasticsearch/ci-test.txt"));
singlePluginInstallAndRemove("elasticsearch/elasticsearch-transport-thrift/1.5.0", null); singlePluginInstallAndRemove("elasticsearch/elasticsearch-transport-thrift/1.5.0", null);
} }
@ -313,7 +321,7 @@ public class PluginManagerTests extends ElasticsearchIntegrationTest {
@Test @Test
@Network @Network
public void testInstallPluginWithMavenCentral() throws IOException { public void testInstallPluginWithMavenCentral() throws IOException {
assumeTrue(isDownloadServiceWorking("http://search.maven.org/", "/")); assumeTrue(isDownloadServiceWorking("search.maven.org", 80, "/"));
singlePluginInstallAndRemove("org.elasticsearch/elasticsearch-transport-thrift/1.5.0", null); singlePluginInstallAndRemove("org.elasticsearch/elasticsearch-transport-thrift/1.5.0", null);
} }
@ -326,20 +334,21 @@ public class PluginManagerTests extends ElasticsearchIntegrationTest {
@Test @Test
@Network @Network
public void testInstallPluginWithGithub() throws IOException { public void testInstallPluginWithGithub() throws IOException {
assumeTrue(isDownloadServiceWorking("https://github.com/", "/")); assumeTrue(isDownloadServiceWorking("github.com", 443, "/"));
singlePluginInstallAndRemove("elasticsearch/kibana", null); singlePluginInstallAndRemove("elasticsearch/kibana", null);
} }
private boolean isDownloadServiceWorking(String url, String resource) { private boolean isDownloadServiceWorking(String host, int port, String resource) {
HttpClient client = new HttpClient(url);
try { try {
if (client.request(resource).errorCode() != 200) { String protocol = port == 443 ? "https" : "http";
logger.warn("[{}{}] download service is not working. Disabling current test.", url, resource); HttpResponse response = new HttpRequestBuilder(HttpClients.createDefault()).protocol(protocol).host(host).port(port).path(resource).execute();
if (response.getStatusCode() != 200) {
logger.warn("[{}{}] download service is not working. Disabling current test.", host, resource);
return false; return false;
} }
return true; return true;
} catch (Throwable t) { } catch (Throwable t) {
logger.warn("[{}{}] download service is not working. Disabling current test.", url, resource); logger.warn("[{}{}] download service is not working. Disabling current test.", host, resource);
} }
return false; return false;
} }

View File

@ -18,21 +18,19 @@
*/ */
package org.elasticsearch.plugin; package org.elasticsearch.plugin;
import com.google.common.collect.Maps; import org.apache.http.impl.client.HttpClients;
import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.http.HttpServerTransport; import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.plugin.responseheader.TestResponseHeaderPlugin; import org.elasticsearch.plugin.responseheader.TestResponseHeaderPlugin;
import org.elasticsearch.rest.RestStatus; import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.helper.HttpClient;
import org.elasticsearch.rest.helper.HttpClientResponse;
import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import org.elasticsearch.test.rest.client.http.HttpRequestBuilder;
import org.elasticsearch.test.rest.client.http.HttpResponse;
import org.junit.Test; import org.junit.Test;
import java.util.Map; import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.*;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
/** /**
@ -53,19 +51,16 @@ public class ResponseHeaderPluginTests extends ElasticsearchIntegrationTest {
@Test @Test
public void testThatSettingHeadersWorks() throws Exception { public void testThatSettingHeadersWorks() throws Exception {
ensureGreen(); ensureGreen();
HttpClientResponse response = httpClient().request("/_protected"); HttpResponse response = httpClient().method("GET").path("/_protected").execute();
assertThat(response.errorCode(), equalTo(RestStatus.UNAUTHORIZED.getStatus())); assertThat(response.getStatusCode(), equalTo(RestStatus.UNAUTHORIZED.getStatus()));
assertThat(response.getHeader("Secret"), equalTo("required")); assertThat(response.getHeaders().get("Secret"), equalTo("required"));
Map<String, String> headers = Maps.newHashMap(); HttpResponse authResponse = httpClient().method("GET").path("/_protected").addHeader("Secret", "password").execute();
headers.put("Secret", "password"); assertThat(authResponse.getStatusCode(), equalTo(RestStatus.OK.getStatus()));
HttpClientResponse authResponse = httpClient().request("GET", "_protected", headers); assertThat(authResponse.getHeaders().get("Secret"), equalTo("granted"));
assertThat(authResponse.errorCode(), equalTo(RestStatus.OK.getStatus()));
assertThat(authResponse.getHeader("Secret"), equalTo("granted"));
} }
private HttpClient httpClient() { private HttpRequestBuilder httpClient() {
HttpServerTransport httpServerTransport = internalCluster().getDataNodeInstance(HttpServerTransport.class); return new HttpRequestBuilder(HttpClients.createDefault()).httpTransport(internalCluster().getDataNodeInstance(HttpServerTransport.class));
return new HttpClient(httpServerTransport.boundAddress().publishAddress());
} }
} }

View File

@ -18,20 +18,23 @@
*/ */
package org.elasticsearch.plugin; package org.elasticsearch.plugin;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.http.HttpServerTransport; import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.rest.RestStatus; import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.helper.HttpClient;
import org.elasticsearch.rest.helper.HttpClientResponse;
import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import org.elasticsearch.test.rest.client.http.HttpRequestBuilder;
import org.elasticsearch.test.rest.client.http.HttpResponse;
import org.junit.Test; import org.junit.Test;
import java.io.File; import java.io.File;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder; import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.*; import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
@ -56,22 +59,23 @@ public class SitePluginTests extends ElasticsearchIntegrationTest {
} }
} }
public HttpClient httpClient() { public HttpRequestBuilder httpClient() {
HttpServerTransport httpServerTransport = internalCluster().getDataNodeInstance(HttpServerTransport.class); RequestConfig.Builder builder = RequestConfig.custom().setRedirectsEnabled(false);
return new HttpClient(httpServerTransport.boundAddress().publishAddress()); CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(builder.build()).build();
return new HttpRequestBuilder(httpClient).httpTransport(internalCluster().getDataNodeInstance(HttpServerTransport.class));
} }
@Test @Test
public void testRedirectSitePlugin() throws Exception { public void testRedirectSitePlugin() throws Exception {
// We use an HTTP Client to test redirection // We use an HTTP Client to test redirection
HttpClientResponse response = httpClient().request("/_plugin/dummy"); HttpResponse response = httpClient().method("GET").path("/_plugin/dummy").execute();
assertThat(response.errorCode(), equalTo(RestStatus.MOVED_PERMANENTLY.getStatus())); assertThat(response.getStatusCode(), equalTo(RestStatus.MOVED_PERMANENTLY.getStatus()));
assertThat(response.response(), containsString("/_plugin/dummy/")); assertThat(response.getBody(), containsString("/_plugin/dummy/"));
// We test the real URL // We test the real URL
response = httpClient().request("/_plugin/dummy/"); response = httpClient().method("GET").path("/_plugin/dummy/").execute();
assertThat(response.errorCode(), equalTo(RestStatus.OK.getStatus())); assertThat(response.getStatusCode(), equalTo(RestStatus.OK.getStatus()));
assertThat(response.response(), containsString("<title>Dummy Site Plugin</title>")); assertThat(response.getBody(), containsString("<title>Dummy Site Plugin</title>"));
} }
/** /**
@ -79,9 +83,9 @@ public class SitePluginTests extends ElasticsearchIntegrationTest {
*/ */
@Test @Test
public void testAnyPage() throws Exception { public void testAnyPage() throws Exception {
HttpClientResponse response = httpClient().request("/_plugin/dummy/index.html"); HttpResponse response = httpClient().path("/_plugin/dummy/index.html").execute();
assertThat(response.errorCode(), equalTo(RestStatus.OK.getStatus())); assertThat(response.getStatusCode(), equalTo(RestStatus.OK.getStatus()));
assertThat(response.response(), containsString("<title>Dummy Site Plugin</title>")); assertThat(response.getBody(), containsString("<title>Dummy Site Plugin</title>"));
} }
/** /**
@ -90,15 +94,15 @@ public class SitePluginTests extends ElasticsearchIntegrationTest {
*/ */
@Test @Test
public void testWelcomePageInSubDirs() throws Exception { public void testWelcomePageInSubDirs() throws Exception {
HttpClientResponse response = httpClient().request("/_plugin/subdir/dir/"); HttpResponse response = httpClient().path("/_plugin/subdir/dir/").execute();
assertThat(response.errorCode(), equalTo(RestStatus.OK.getStatus())); assertThat(response.getStatusCode(), equalTo(RestStatus.OK.getStatus()));
assertThat(response.response(), containsString("<title>Dummy Site Plugin (subdir)</title>")); assertThat(response.getBody(), containsString("<title>Dummy Site Plugin (subdir)</title>"));
response = httpClient().request("/_plugin/subdir/dir_without_index/"); response = httpClient().path("/_plugin/subdir/dir_without_index/").execute();
assertThat(response.errorCode(), equalTo(RestStatus.FORBIDDEN.getStatus())); assertThat(response.getStatusCode(), equalTo(RestStatus.FORBIDDEN.getStatus()));
response = httpClient().request("/_plugin/subdir/dir_without_index/page.html"); response = httpClient().path("/_plugin/subdir/dir_without_index/page.html").execute();
assertThat(response.errorCode(), equalTo(RestStatus.OK.getStatus())); assertThat(response.getStatusCode(), equalTo(RestStatus.OK.getStatus()));
assertThat(response.response(), containsString("<title>Dummy Site Plugin (page)</title>")); assertThat(response.getBody(), containsString("<title>Dummy Site Plugin (page)</title>"));
} }
} }

View File

@ -1,120 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.rest.helper;
import com.google.common.base.Charsets;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.io.Streams;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map;
public class HttpClient {
private final URL baseUrl;
public HttpClient(TransportAddress transportAddress) {
InetSocketAddress address = ((InetSocketTransportAddress) transportAddress).address();
try {
baseUrl = new URL("http", address.getAddress().getHostAddress(), address.getPort(), "/");
} catch (MalformedURLException e) {
throw new ElasticsearchException("", e);
}
}
public HttpClient(String url) {
try {
baseUrl = new URL(url);
} catch (MalformedURLException e) {
throw new ElasticsearchException("", e);
}
}
public HttpClient(URL url) {
baseUrl = url;
}
public HttpClientResponse request(String path) {
return request("GET", path);
}
public HttpClientResponse request(String method, String path) {
return request(method, path, null);
}
public HttpClientResponse request(String method, String path, Map<String, String> headers) {
URL url;
try {
url = new URL(baseUrl, path);
} catch (MalformedURLException e) {
throw new ElasticsearchException("Cannot parse " + path, e);
}
HttpURLConnection urlConnection;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod(method);
if (headers != null) {
for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
urlConnection.setRequestProperty(headerEntry.getKey(), headerEntry.getValue());
}
}
urlConnection.connect();
} catch (IOException e) {
throw new ElasticsearchException("", e);
}
int errorCode = -1;
Map<String, List<String>> respHeaders = null;
try {
errorCode = urlConnection.getResponseCode();
respHeaders = urlConnection.getHeaderFields();
InputStream inputStream = urlConnection.getInputStream();
String body = null;
try {
body = Streams.copyToString(new InputStreamReader(inputStream, Charsets.UTF_8));
} catch (IOException e1) {
throw new ElasticsearchException("problem reading error stream", e1);
}
return new HttpClientResponse(body, errorCode, respHeaders, null);
} catch (IOException e) {
InputStream errStream = urlConnection.getErrorStream();
String body = null;
if (errStream != null) {
try {
body = Streams.copyToString(new InputStreamReader(errStream, Charsets.UTF_8));
} catch (IOException e1) {
throw new ElasticsearchException("problem reading error stream", e1);
}
}
return new HttpClientResponse(body, errorCode, respHeaders, e);
} finally {
urlConnection.disconnect();
}
}
}

View File

@ -1,63 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.rest.helper;
import java.util.List;
import java.util.Map;
public class HttpClientResponse {
private final String response;
private final int errorCode;
private Map<String, List<String>> headers;
private final Throwable e;
public HttpClientResponse(String response, int errorCode, Map<String, List<String>> headers, Throwable e) {
this.response = response;
this.errorCode = errorCode;
this.headers = headers;
this.e = e;
}
public String response() {
return response;
}
public int errorCode() {
return errorCode;
}
public Throwable cause() {
return e;
}
public Map<String, List<String>> getHeaders() {
return headers;
}
public String getHeader(String name) {
if (headers == null) {
return null;
}
List<String> vals = headers.get(name);
if (vals == null || vals.size() == 0) {
return null;
}
return vals.iterator().next();
}
}

View File

@ -20,6 +20,7 @@ package org.elasticsearch.test.rest.client.http;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*; import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity; import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
@ -27,6 +28,9 @@ import org.apache.lucene.util.IOUtils;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.http.HttpServerTransport;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -46,6 +50,8 @@ public class HttpRequestBuilder {
private final CloseableHttpClient httpClient; private final CloseableHttpClient httpClient;
private String protocol = "http";
private String host; private String host;
private int port; private int port;
@ -54,6 +60,8 @@ public class HttpRequestBuilder {
private final Map<String, String> params = Maps.newHashMap(); private final Map<String, String> params = Maps.newHashMap();
private final Map<String, String> headers = Maps.newHashMap();
private String method = HttpGetWithEntity.METHOD_NAME; private String method = HttpGetWithEntity.METHOD_NAME;
private String body; private String body;
@ -67,6 +75,11 @@ public class HttpRequestBuilder {
return this; return this;
} }
public HttpRequestBuilder httpTransport(HttpServerTransport httpServerTransport) {
InetSocketTransportAddress transportAddress = (InetSocketTransportAddress) httpServerTransport.boundAddress().publishAddress();
return host(transportAddress.address().getHostName()).port(transportAddress.address().getPort());
}
public HttpRequestBuilder port(int port) { public HttpRequestBuilder port(int port) {
this.port = port; this.port = port;
return this; return this;
@ -82,6 +95,16 @@ public class HttpRequestBuilder {
return this; return this;
} }
public HttpRequestBuilder addHeader(String name, String value) {
this.headers.put(name, value);
return this;
}
public HttpRequestBuilder protocol(String protocol) {
this.protocol = protocol;
return this;
}
public HttpRequestBuilder method(String method) { public HttpRequestBuilder method(String method) {
this.method = method; this.method = method;
return this; return this;
@ -95,26 +118,21 @@ public class HttpRequestBuilder {
} }
public HttpResponse execute() throws IOException { public HttpResponse execute() throws IOException {
CloseableHttpResponse closeableHttpResponse = null; HttpUriRequest httpUriRequest = buildRequest();
try { if (logger.isTraceEnabled()) {
HttpUriRequest httpUriRequest = buildRequest(); StringBuilder stringBuilder = new StringBuilder(httpUriRequest.getMethod()).append(" ").append(httpUriRequest.getURI());
if (logger.isTraceEnabled()) { if (Strings.hasLength(body)) {
StringBuilder stringBuilder = new StringBuilder(httpUriRequest.getMethod()).append(" ").append(httpUriRequest.getURI()); stringBuilder.append("\n").append(body);
if (Strings.hasLength(body)) {
stringBuilder.append("\n").append(body);
}
logger.trace("sending request \n{}", stringBuilder.toString());
} }
closeableHttpResponse = httpClient.execute(httpUriRequest); logger.trace("sending request \n{}", stringBuilder.toString());
}
for (Map.Entry<String, String> entry : this.headers.entrySet()) {
httpUriRequest.addHeader(entry.getKey(), entry.getValue());
}
try (CloseableHttpResponse closeableHttpResponse = httpClient.execute(httpUriRequest)) {
HttpResponse httpResponse = new HttpResponse(httpUriRequest, closeableHttpResponse); HttpResponse httpResponse = new HttpResponse(httpUriRequest, closeableHttpResponse);
logger.trace("got response \n{}\n{}", closeableHttpResponse, httpResponse.hasBody() ? httpResponse.getBody() : ""); logger.trace("got response \n{}\n{}", closeableHttpResponse, httpResponse.hasBody() ? httpResponse.getBody() : "");
return httpResponse; return httpResponse;
} finally {
try {
IOUtils.close(closeableHttpResponse);
} catch (IOException e) {
logger.error("error closing http response", e);
}
} }
} }
@ -152,7 +170,7 @@ public class HttpRequestBuilder {
query = Joiner.on('&').withKeyValueSeparator("=").join(params); query = Joiner.on('&').withKeyValueSeparator("=").join(params);
} }
try { try {
return new URI("http", null, host, port, path, query, null); return new URI(protocol, null, host, port, path, query, null);
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
throw new IllegalArgumentException(e); throw new IllegalArgumentException(e);
} }

View File

@ -18,6 +18,7 @@
*/ */
package org.elasticsearch.test.rest.client.http; package org.elasticsearch.test.rest.client.http;
import org.apache.http.Header;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.HttpUriRequest;
@ -26,6 +27,8 @@ import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.logging.Loggers;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/** /**
* Response obtained from an http request * Response obtained from an http request
@ -39,11 +42,15 @@ public class HttpResponse {
private final int statusCode; private final int statusCode;
private final String reasonPhrase; private final String reasonPhrase;
private final String body; private final String body;
private final Map<String, String> headers = new HashMap<>();
HttpResponse(HttpUriRequest httpRequest, CloseableHttpResponse httpResponse) { HttpResponse(HttpUriRequest httpRequest, CloseableHttpResponse httpResponse) {
this.httpRequest = httpRequest; this.httpRequest = httpRequest;
this.statusCode = httpResponse.getStatusLine().getStatusCode(); this.statusCode = httpResponse.getStatusLine().getStatusCode();
this.reasonPhrase = httpResponse.getStatusLine().getReasonPhrase(); this.reasonPhrase = httpResponse.getStatusLine().getReasonPhrase();
for (Header header : httpResponse.getAllHeaders()) {
this.headers.put(header.getName(), header.getValue());
}
if (httpResponse.getEntity() != null) { if (httpResponse.getEntity() != null) {
try { try {
this.body = EntityUtils.toString(httpResponse.getEntity(), HttpRequestBuilder.DEFAULT_CHARSET); this.body = EntityUtils.toString(httpResponse.getEntity(), HttpRequestBuilder.DEFAULT_CHARSET);
@ -86,6 +93,10 @@ public class HttpResponse {
return !HttpHead.METHOD_NAME.equals(httpRequest.getMethod()); return !HttpHead.METHOD_NAME.equals(httpRequest.getMethod());
} }
public Map<String, String> getHeaders() {
return headers;
}
@Override @Override
public String toString() { public String toString() {
StringBuilder stringBuilder = new StringBuilder(statusCode).append(" ").append(reasonPhrase); StringBuilder stringBuilder = new StringBuilder(statusCode).append(" ").append(reasonPhrase);