summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorThomas Becker2011-09-23 11:43:07 (EDT)
committer Jesse McConnell2011-09-26 18:50:27 (EDT)
commit88ce9aceb25fd3bce460904a66c98095391f220b (patch)
treeba0b14b1364485a1453e0a993db8304d9e01841a
parentb94f901433df1554ab5b0ab1b106e619de508958 (diff)
downloadorg.eclipse.jetty.project-88ce9aceb25fd3bce460904a66c98095391f220b.zip
org.eclipse.jetty.project-88ce9aceb25fd3bce460904a66c98095391f220b.tar.gz
org.eclipse.jetty.project-88ce9aceb25fd3bce460904a66c98095391f220b.tar.bz2
Added ProxyRule.java and ProxyRuleTest.java
-rw-r--r--jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ProxyRule.java282
-rw-r--r--jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ProxyRuleTest.java77
2 files changed, 359 insertions, 0 deletions
diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ProxyRule.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ProxyRule.java
new file mode 100644
index 0000000..b5516bc
--- /dev/null
+++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ProxyRule.java
@@ -0,0 +1,282 @@
+package org.eclipse.jetty.rewrite.handler;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.util.Enumeration;
+import java.util.HashSet;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.HttpExchange;
+import org.eclipse.jetty.http.HttpHeaderValues;
+import org.eclipse.jetty.http.HttpHeaders;
+import org.eclipse.jetty.http.HttpSchemes;
+import org.eclipse.jetty.http.HttpURI;
+import org.eclipse.jetty.io.Buffer;
+import org.eclipse.jetty.io.EofException;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+
+public class ProxyRule extends Rule
+{
+ private static final Logger _log = Log.getLogger(ProxyRule.class);
+
+ protected HttpClient _client;
+ protected String _hostHeader;
+
+ protected HashSet<String> _DontProxyHeaders = new HashSet<String>();
+ {
+ _DontProxyHeaders.add("proxy-connection");
+ _DontProxyHeaders.add("connection");
+ _DontProxyHeaders.add("keep-alive");
+ _DontProxyHeaders.add("transfer-encoding");
+ _DontProxyHeaders.add("te");
+ _DontProxyHeaders.add("trailer");
+ _DontProxyHeaders.add("proxy-authorization");
+ _DontProxyHeaders.add("proxy-authenticate");
+ _DontProxyHeaders.add("upgrade");
+ }
+
+ public ProxyRule()
+ {
+ _handling = true;
+ _terminating = true;
+
+ }
+
+ private void initializeClient() throws Exception
+ {
+ _client = new HttpClient();
+ _client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
+ _client.setThreadPool(new QueuedThreadPool());
+ _client.start();
+ }
+
+ /* ------------------------------------------------------------ */
+ protected HttpURI proxyHttpURI(String scheme, String serverName, int serverPort, String uri) throws MalformedURLException
+ {
+ return new HttpURI(scheme + "://" + serverName + ":" + serverPort + uri);
+ }
+
+ @Override
+ public String matchAndApply(String target, HttpServletRequest req, HttpServletResponse res) throws IOException
+ {
+ synchronized (this)
+ {
+ if (_client == null)
+ {
+ try
+ {
+ initializeClient();
+ }
+ catch (Exception e)
+ {
+ throw new IOException("Unable to proxy: " + e.getMessage());
+ }
+ }
+ }
+
+ final HttpServletRequest request = (HttpServletRequest)req;
+ final HttpServletResponse response = (HttpServletResponse)res;
+
+ final int debug = _log.isDebugEnabled()?request.hashCode():0;
+
+ final InputStream in = request.getInputStream();
+ final OutputStream out = response.getOutputStream();
+
+ String uri = request.getRequestURI();
+ if (request.getQueryString() != null)
+ uri += "?" + request.getQueryString();
+
+ HttpURI url = proxyHttpURI(request.getScheme(),request.getServerName(),request.getServerPort(),uri);
+
+ if (debug != 0)
+ _log.debug(debug + " proxy " + uri + "-->" + url);
+
+ if (url == null)
+ {
+ response.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return target;
+ }
+
+ HttpExchange exchange = new HttpExchange()
+ {
+ protected void onRequestCommitted() throws IOException
+ {
+ }
+
+ protected void onRequestComplete() throws IOException
+ {
+ }
+
+ protected void onResponseComplete() throws IOException
+ {
+ if (debug != 0)
+ _log.debug(debug + " complete");
+ }
+
+ protected void onResponseContent(Buffer content) throws IOException
+ {
+ if (debug != 0)
+ _log.debug(debug + " content" + content.length());
+ content.writeTo(out);
+ }
+
+ protected void onResponseHeaderComplete() throws IOException
+ {
+ }
+
+ protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
+ {
+ if (debug != 0)
+ _log.debug(debug + " " + version + " " + status + " " + reason);
+
+ if (reason != null && reason.length() > 0)
+ response.setStatus(status,reason.toString());
+ else
+ response.setStatus(status);
+ }
+
+ protected void onResponseHeader(Buffer name, Buffer value) throws IOException
+ {
+ String s = name.toString().toLowerCase();
+ if (!_DontProxyHeaders.contains(s) || (HttpHeaders.CONNECTION_BUFFER.equals(name) && HttpHeaderValues.CLOSE_BUFFER.equals(value)))
+ {
+ if (debug != 0)
+ _log.debug(debug + " " + name + ": " + value);
+
+ response.addHeader(name.toString(),value.toString());
+ }
+ else if (debug != 0)
+ _log.debug(debug + " " + name + "! " + value);
+ }
+
+ protected void onConnectionFailed(Throwable ex)
+ {
+ _log.warn(ex.toString());
+ _log.debug(ex);
+ if (!response.isCommitted())
+ {
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ protected void onException(Throwable ex)
+ {
+ if (ex instanceof EofException)
+ {
+ _log.ignore(ex);
+ return;
+ }
+ _log.warn(ex.toString());
+ _log.debug(ex);
+ if (!response.isCommitted())
+ {
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ protected void onExpire()
+ {
+ if (!response.isCommitted())
+ {
+ response.setStatus(HttpServletResponse.SC_GATEWAY_TIMEOUT);
+ }
+ }
+
+ };
+
+ exchange.setScheme(HttpSchemes.HTTPS.equals(request.getScheme())?HttpSchemes.HTTPS_BUFFER:HttpSchemes.HTTP_BUFFER);
+ exchange.setMethod(request.getMethod());
+ exchange.setURL(url.toString());
+ exchange.setVersion(request.getProtocol());
+
+ if (debug != 0)
+ _log.debug(debug + " " + request.getMethod() + " " + url + " " + request.getProtocol());
+
+ // check connection header
+ String connectionHdr = request.getHeader("Connection");
+ if (connectionHdr != null)
+ {
+ connectionHdr = connectionHdr.toLowerCase();
+ if (connectionHdr.indexOf("keep-alive") < 0 && connectionHdr.indexOf("close") < 0)
+ connectionHdr = null;
+ }
+
+ // force host
+ if (_hostHeader != null)
+ exchange.setRequestHeader("Host",_hostHeader);
+
+ // copy headers
+ boolean xForwardedFor = false;
+ boolean hasContent = false;
+ long contentLength = -1;
+ Enumeration<?> enm = request.getHeaderNames();
+ while (enm.hasMoreElements())
+ {
+ // TODO could be better than this!
+ String hdr = (String)enm.nextElement();
+ String lhdr = hdr.toLowerCase();
+
+ if (_DontProxyHeaders.contains(lhdr))
+ continue;
+ if (connectionHdr != null && connectionHdr.indexOf(lhdr) >= 0)
+ continue;
+ if (_hostHeader != null && "host".equals(lhdr))
+ continue;
+
+ if ("content-type".equals(lhdr))
+ hasContent = true;
+ else if ("content-length".equals(lhdr))
+ {
+ contentLength = request.getContentLength();
+ exchange.setRequestHeader(HttpHeaders.CONTENT_LENGTH,Long.toString(contentLength));
+ if (contentLength > 0)
+ hasContent = true;
+ }
+ else if ("x-forwarded-for".equals(lhdr))
+ xForwardedFor = true;
+
+ Enumeration<?> vals = request.getHeaders(hdr);
+ while (vals.hasMoreElements())
+ {
+ String val = (String)vals.nextElement();
+ if (val != null)
+ {
+ if (debug != 0)
+ _log.debug(debug + " " + hdr + ": " + val);
+
+ exchange.setRequestHeader(hdr,val);
+ }
+ }
+ }
+
+ // Proxy headers
+ exchange.setRequestHeader("Via","1.1 (jetty)");
+ if (!xForwardedFor)
+ {
+ exchange.addRequestHeader("X-Forwarded-For",request.getRemoteAddr());
+ exchange.addRequestHeader("X-Forwarded-Proto",request.getScheme());
+ exchange.addRequestHeader("X-Forwarded-Host",request.getServerName());
+ exchange.addRequestHeader("X-Forwarded-Server",request.getLocalName());
+ }
+
+ if (hasContent)
+ exchange.setRequestContentSource(in);
+
+ /*
+ * we need to set the timeout on the continuation to take into account the timeout of the HttpClient and the HttpExchange
+ */
+ long ctimeout = (_client.getTimeout() > exchange.getTimeout())?_client.getTimeout():exchange.getTimeout();
+
+ _client.send(exchange);
+
+ return target;
+ }
+
+}
diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ProxyRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ProxyRuleTest.java
new file mode 100644
index 0000000..9f021a5
--- /dev/null
+++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ProxyRuleTest.java
@@ -0,0 +1,77 @@
+// ========================================================================
+// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+package org.eclipse.jetty.rewrite.handler;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URLEncoder;
+
+import org.eclipse.jetty.client.Address;
+import org.eclipse.jetty.client.ContentExchange;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.HttpExchange;
+import org.eclipse.jetty.http.HttpHeaders;
+import org.eclipse.jetty.http.HttpMethods;
+import org.eclipse.jetty.toolchain.test.SimpleRequest;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class ProxyRuleTest extends AbstractRuleTestCase
+{
+ private ProxyRule _rule;
+ private RewriteHandler _handler;
+
+ @Before
+ public void init() throws Exception
+ {
+ start(false);
+ _rule = new ProxyRule();
+
+ _handler = new RewriteHandler();
+ _handler.setRewriteRequestURI(true);
+
+ _handler.setRules(new Rule[] { _rule } );
+
+ _server.setHandler(_handler);
+ }
+
+ @After
+ public void destroy()
+ {
+ _rule = null;
+ }
+
+ @Test
+ public void testProxy() throws Exception
+ {
+// HttpClient httpClient = new HttpClient();
+// httpClient.setProxy(new Address("localhost", proxyPort()));
+// httpClient.start();
+//
+// try
+// {
+// ContentExchange exchange = new ContentExchange(true);
+// exchange.setMethod(HttpMethods.GET);
+// String body = "BODY";
+// exchange.setURL("https://localhost:" + serverConnector.getLocalPort() + "/echo?body=" + URLEncoder.encode(body, "UTF-8"));
+//
+// httpClient.send(exchange);
+// assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
+// //_rule.matchAndApply(null, _request, _response);
+//
+// //assertEquals(location, _response.getHeader(HttpHeaders.LOCATION));
+ }
+}