package io.searchbox.client.http; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.nio.charset.Charset; import org.littleshoot.proxy.HttpFilters; import org.littleshoot.proxy.HttpFiltersAdapter; import org.littleshoot.proxy.HttpFiltersSourceAdapter; import org.littleshoot.proxy.HttpProxyServer; import org.littleshoot.proxy.HttpProxyServerBootstrap; import org.littleshoot.proxy.impl.DefaultHttpProxyServer; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.HttpObject; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; public class FailingProxy { private final HttpProxyServer server; private String errorContentType = "text/html"; private HttpResponseStatus errorStatus = new HttpResponseStatus(500, "This proxy always fails"); private String errorMessage = "<html>" + " <head><title>This proxy always fails</title></head>" + "<body>" + " <h1>This proxy always fails</h1>" + "</body>" + "</html>"; public FailingProxy() throws IOException { final HttpProxyServerBootstrap bootstrap = DefaultHttpProxyServer .bootstrap() .withPort(getUnusedPort()) .withTransparent(true) .withFiltersSource(new FailingSourceAdapter()) ; server = bootstrap.start(); } public void setErrorStatus(final HttpResponseStatus errorStatus) { this.errorStatus = errorStatus; } public void setErrorContentType(final String errorContentType) { this.errorContentType = errorContentType; } public void setErrorMessage(final String errorMessage) { this.errorMessage = errorMessage; } public String getUrl() { final InetSocketAddress listenAddress = server.getListenAddress(); final String host = listenAddress.getHostName(); final int port = listenAddress.getPort(); return String.format("http://%s:%d/", host, port); } public void stop() { server.stop(); } private static int getUnusedPort() throws IOException { final Socket deadSocket = new Socket(); deadSocket.bind(null); final int port = deadSocket.getLocalPort(); deadSocket.close(); return port; } private class FailingSourceAdapter extends HttpFiltersSourceAdapter { @Override public HttpFilters filterRequest(final HttpRequest originalRequest) { return new FailingFilterAdapter(originalRequest); } } private class FailingFilterAdapter extends HttpFiltersAdapter { public FailingFilterAdapter(final HttpRequest originalRequest) { super(originalRequest); } @Override public HttpResponse proxyToServerRequest(final HttpObject httpObject) { ByteBuf buf = Unpooled.wrappedBuffer(errorMessage.getBytes(Charset.forName("UTF-8"))); final DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, errorStatus, buf); response.headers().set("Content-Type", errorContentType); return response; } } }