diff --git a/pom.xml b/pom.xml index 73b6685..f515161 100644 --- a/pom.xml +++ b/pom.xml @@ -108,6 +108,19 @@ 11.0.15 test + + + org.littleshoot + littleproxy + 1.1.2 + test + + + org.slf4j + slf4j-jcl + 1.7.36 + test + diff --git a/src/main/java/org/mitre/dsmiley/httpproxy/ProxyServlet.java b/src/main/java/org/mitre/dsmiley/httpproxy/ProxyServlet.java index 41b2983..b7cada9 100755 --- a/src/main/java/org/mitre/dsmiley/httpproxy/ProxyServlet.java +++ b/src/main/java/org/mitre/dsmiley/httpproxy/ProxyServlet.java @@ -29,8 +29,10 @@ import org.apache.http.client.methods.AbortableHttpRequest; import org.apache.http.client.utils.URIUtils; import org.apache.http.config.SocketConfig; +import org.apache.http.conn.routing.HttpRoutePlanner; import org.apache.http.entity.InputStreamEntity; import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.DefaultProxyRoutePlanner; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHttpEntityEnclosingRequest; import org.apache.http.message.BasicHttpRequest; @@ -111,6 +113,11 @@ public class ProxyServlet extends HttpServlet { /** The parameter name for the target (destination) URI to proxy to. */ public static final String P_TARGET_URI = "targetUri"; + /** + * Parameter for an (optional) HTTP proxy that should be used for any request to the target. Format: host:port. + */ + public static final String P_HTTP_PROXY_HOST_AND_PORT = "http.proxy.host-and-port"; + protected static final String ATTR_TARGET_URI = ProxyServlet.class.getSimpleName() + ".targetUri"; protected static final String ATTR_TARGET_HOST = @@ -139,6 +146,7 @@ public class ProxyServlet extends HttpServlet { protected String targetUri; protected URI targetUriObj;//new URI(targetUri) protected HttpHost targetHost;//URIUtils.extractHost(targetUriObj); + protected HttpHost httpProxyHost; private HttpClient proxyClient; @@ -226,6 +234,15 @@ public void init() throws ServletException { this.doHandleCompression = Boolean.parseBoolean(doHandleCompression); } + String proxyHostAndPortString = this.getConfigParam(P_HTTP_PROXY_HOST_AND_PORT); + if (proxyHostAndPortString != null) { + String[] proxyParams = proxyHostAndPortString.split(":"); + if (proxyParams.length != 2) { + throw new ServletException("Invalid config parameter: " + P_HTTP_PROXY_HOST_AND_PORT + " - format must be: HOST:PORT"); + } + this.httpProxyHost = new HttpHost(proxyParams[0], Integer.parseInt(proxyParams[1])); + } + initTarget();//sets target* proxyClient = createHttpClient(); @@ -289,6 +306,12 @@ protected HttpClient createHttpClient() { if (useSystemProperties) clientBuilder = clientBuilder.useSystemProperties(); + + if (httpProxyHost != null) { + HttpRoutePlanner proxyRoutePlanner = new DefaultProxyRoutePlanner(httpProxyHost); + clientBuilder.setRoutePlanner(proxyRoutePlanner); + } + return buildHttpClient(clientBuilder); } diff --git a/src/test/java/org/mitre/dsmiley/httpproxy/ProxyServletThroughHttpProxyTest.java b/src/test/java/org/mitre/dsmiley/httpproxy/ProxyServletThroughHttpProxyTest.java new file mode 100644 index 0000000..14ff556 --- /dev/null +++ b/src/test/java/org/mitre/dsmiley/httpproxy/ProxyServletThroughHttpProxyTest.java @@ -0,0 +1,30 @@ +package org.mitre.dsmiley.httpproxy; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.littleshoot.proxy.HttpProxyServer; +import org.littleshoot.proxy.impl.DefaultHttpProxyServer; + +import java.util.Properties; + +public class ProxyServletThroughHttpProxyTest extends ProxyServletTest { + + private static HttpProxyServer proxyServer; + + @BeforeClass + public static void setUpBeforeClass() { + proxyServer = DefaultHttpProxyServer.bootstrap().start(); + } + + @AfterClass + public static void tearDownAfterClass() { + proxyServer.stop(); + } + + @Override + protected void setUpServlet(Properties servletProps) { + servletProps.setProperty(ProxyServlet.P_HTTP_PROXY_HOST_AND_PORT, "localhost:" + proxyServer.getListenAddress().getPort()); + super.setUpServlet(servletProps); + } + +}