package io.searchbox.client.http;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpRequest;
import io.searchbox.client.JestClientFactory;
import io.searchbox.client.JestResult;
import io.searchbox.client.JestResultHandler;
import io.searchbox.client.config.HttpClientConfig;
import io.searchbox.indices.Stats;
import org.apache.http.HttpHost;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.transport.Netty4Plugin;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.littleshoot.proxy.HttpFilters;
import org.littleshoot.proxy.HttpFiltersAdapter;
import org.littleshoot.proxy.HttpFiltersSourceAdapter;
import org.littleshoot.proxy.HttpProxyServer;
import org.littleshoot.proxy.impl.DefaultHttpProxyServer;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author cihat keser
*/
@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST, numDataNodes = 0)
public class JestHttpClientConfiguredProxyIntegrationTest extends ESIntegTestCase {
private static final int PROXY_PORT = 8770;
private AtomicInteger numProxyRequests = new AtomicInteger(0);
private JestClientFactory factory = new JestClientFactory();
private HttpProxyServer server = null;
private JestHttpClient customJestClient = null;
@Before
public void setup() {
server = DefaultHttpProxyServer
.bootstrap()
.withPort(PROXY_PORT)
.withFiltersSource(new HttpFiltersSourceAdapter() {
public HttpFilters filterRequest(HttpRequest originalRequest, ChannelHandlerContext ctx) {
return new HttpFiltersAdapter(originalRequest) {
@Override
public void proxyToServerRequestSent() {
numProxyRequests.incrementAndGet();
}
};
}
}).start();
}
@After
public void destroy() {
if (server != null) server.stop();
if (customJestClient != null) customJestClient.shutdownClient();
}
@Test
public void testConnectionThroughConfiguredProxy() throws IOException, ExecutionException, InterruptedException {
internalCluster().ensureAtLeastNumDataNodes(1);
assertEquals("All nodes in cluster should have HTTP endpoint exposed", 1, cluster().httpAddresses().length);
// sanity check - assert we cant connect without configuring proxy
factory.setHttpClientConfig(new HttpClientConfig
.Builder("http://localhost:" + cluster().httpAddresses()[0].getPort())
.build());
customJestClient = (JestHttpClient) factory.getObject();
JestResult result = customJestClient.execute(new Stats.Builder().build());
assertTrue(result.getErrorMessage(), result.isSucceeded());
assertEquals(0, numProxyRequests.intValue());
customJestClient.shutdownClient();
// test sync execution
factory.setHttpClientConfig(new HttpClientConfig
.Builder("http://localhost:" + cluster().httpAddresses()[0].getPort())
.proxy(new HttpHost("localhost", PROXY_PORT))
.build());
customJestClient = (JestHttpClient) factory.getObject();
result = customJestClient.execute(new Stats.Builder().build());
assertTrue(result.getErrorMessage(), result.isSucceeded());
assertEquals(1, numProxyRequests.intValue());
customJestClient.shutdownClient();
// test async execution
factory.setHttpClientConfig(new HttpClientConfig
.Builder("http://localhost:" + cluster().httpAddresses()[0].getPort())
.proxy(new HttpHost("localhost", PROXY_PORT))
.multiThreaded(true)
.build());
customJestClient = (JestHttpClient) factory.getObject();
final CountDownLatch actionExecuted = new CountDownLatch(1);
customJestClient.executeAsync(new Stats.Builder().build(), new JestResultHandler<JestResult>() {
@Override
public void completed(JestResult result) {
actionExecuted.countDown();
}
@Override
public void failed(Exception ex) {
throw new RuntimeException(ex);
}
});
boolean finishedAsync = actionExecuted.await(2, TimeUnit.SECONDS);
if (!finishedAsync) {
fail("Execution took too long to complete");
}
assertEquals(2, numProxyRequests.intValue());
customJestClient.shutdownClient();
}
@Override
protected Settings nodeSettings(int nodeOrdinal) {
return Settings.builder().put(super.nodeSettings(nodeOrdinal))
.put(NetworkModule.HTTP_TYPE_KEY, Netty4Plugin.NETTY_HTTP_TRANSPORT_NAME)
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
.build();
}
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Collections.singletonList(Netty4Plugin.class);
}
}