Merged branch 'jetty-9.2.x' into 'master'.
This commit is contained in:
commit
9983f4680e
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.proxy;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
|
@ -33,6 +34,7 @@ import java.util.concurrent.TimeoutException;
|
|||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.UnavailableException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -611,4 +613,73 @@ public abstract class AbstractProxyServlet extends HttpServlet
|
|||
{
|
||||
return System.identityHashCode(clientRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Utility class that implement transparent proxy functionalities.</p>
|
||||
* <p>Configuration parameters:</p>
|
||||
* <ul>
|
||||
* <li>{@code proxyTo} - a mandatory URI like http://host:80/context to which the request is proxied.</li>
|
||||
* <li>{@code prefix} - an optional URI prefix that is stripped from the start of the forwarded URI.</li>
|
||||
* </ul>
|
||||
* <p>For example, if a request is received at "/foo/bar", the {@code proxyTo} parameter is
|
||||
* "http://host:80/context" and the {@code prefix} parameter is "/foo", then the request would
|
||||
* be proxied to "http://host:80/context/bar".
|
||||
*/
|
||||
protected static class TransparentDelegate
|
||||
{
|
||||
private final ProxyServlet proxyServlet;
|
||||
private String _proxyTo;
|
||||
private String _prefix;
|
||||
|
||||
protected TransparentDelegate(ProxyServlet proxyServlet)
|
||||
{
|
||||
this.proxyServlet = proxyServlet;
|
||||
}
|
||||
|
||||
protected void init(ServletConfig config) throws ServletException
|
||||
{
|
||||
_proxyTo = config.getInitParameter("proxyTo");
|
||||
if (_proxyTo == null)
|
||||
throw new UnavailableException("Init parameter 'proxyTo' is required.");
|
||||
|
||||
String prefix = config.getInitParameter("prefix");
|
||||
if (prefix != null)
|
||||
{
|
||||
if (!prefix.startsWith("/"))
|
||||
throw new UnavailableException("Init parameter 'prefix' must start with a '/'.");
|
||||
_prefix = prefix;
|
||||
}
|
||||
|
||||
// Adjust prefix value to account for context path
|
||||
String contextPath = config.getServletContext().getContextPath();
|
||||
_prefix = _prefix == null ? contextPath : (contextPath + _prefix);
|
||||
|
||||
if (proxyServlet._log.isDebugEnabled())
|
||||
proxyServlet._log.debug(config.getServletName() + " @ " + _prefix + " to " + _proxyTo);
|
||||
}
|
||||
|
||||
protected String rewriteTarget(HttpServletRequest request)
|
||||
{
|
||||
String path = request.getRequestURI();
|
||||
if (!path.startsWith(_prefix))
|
||||
return null;
|
||||
|
||||
StringBuilder uri = new StringBuilder(_proxyTo);
|
||||
if (_proxyTo.endsWith("/"))
|
||||
uri.setLength(uri.length() - 1);
|
||||
String rest = path.substring(_prefix.length());
|
||||
if (!rest.startsWith("/"))
|
||||
uri.append("/");
|
||||
uri.append(rest);
|
||||
String query = request.getQueryString();
|
||||
if (query != null)
|
||||
uri.append("?").append(query);
|
||||
URI rewrittenURI = URI.create(uri.toString()).normalize();
|
||||
|
||||
if (!proxyServlet.validateDestination(rewrittenURI.getHost(), rewrittenURI.getPort()))
|
||||
return null;
|
||||
|
||||
return rewrittenURI.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.zip.GZIPOutputStream;
|
|||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.ReadListener;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
|
@ -194,6 +195,29 @@ public class AsyncMiddleManServlet extends AbstractProxyServlet
|
|||
((Destroyable)serverTransformer).destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Convenience extension of {@link AsyncMiddleManServlet} that offers transparent proxy functionalities.</p>
|
||||
*
|
||||
* @see TransparentDelegate
|
||||
*/
|
||||
public static class Transparent extends ProxyServlet
|
||||
{
|
||||
private final TransparentDelegate delegate = new TransparentDelegate(this);
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig config) throws ServletException
|
||||
{
|
||||
super.init(config);
|
||||
delegate.init(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String rewriteTarget(HttpServletRequest request)
|
||||
{
|
||||
return delegate.rewriteTarget(request);
|
||||
}
|
||||
}
|
||||
|
||||
protected class ProxyReader extends IteratingCallback implements ReadListener
|
||||
{
|
||||
private final byte[] buffer = new byte[getHttpClient().getRequestBufferSize()];
|
||||
|
@ -750,5 +774,4 @@ public class AsyncMiddleManServlet extends AbstractProxyServlet
|
|||
return ByteBuffer.wrap(gzipBytes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -99,6 +99,11 @@ public class AsyncProxyServlet extends ProxyServlet
|
|||
return new StreamWriter(request, proxyResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Convenience extension of {@link AsyncProxyServlet} that offers transparent proxy functionalities.</p>
|
||||
*
|
||||
* @see TransparentDelegate
|
||||
*/
|
||||
public static class Transparent extends AsyncProxyServlet
|
||||
{
|
||||
private final TransparentDelegate delegate = new TransparentDelegate(this);
|
||||
|
|
|
@ -20,14 +20,12 @@ package org.eclipse.jetty.proxy;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.UnavailableException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -128,15 +126,9 @@ public class ProxyServlet extends AbstractProxyServlet
|
|||
}
|
||||
|
||||
/**
|
||||
* This convenience extension to {@link ProxyServlet} configures the servlet as a transparent proxy.
|
||||
* This servlet is configured with the following init parameters:
|
||||
* <ul>
|
||||
* <li>proxyTo - a mandatory URI like http://host:80/context to which the request is proxied.</li>
|
||||
* <li>prefix - an optional URI prefix that is stripped from the start of the forwarded URI.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For example, if a request is received at "/foo/bar", the 'proxyTo' parameter is "http://host:80/context"
|
||||
* and the 'prefix' parameter is "/foo", then the request would be proxied to "http://host:80/context/bar".
|
||||
* <p>Convenience extension of {@link ProxyServlet} that offers transparent proxy functionalities.</p>
|
||||
*
|
||||
* @see TransparentDelegate
|
||||
*/
|
||||
public static class Transparent extends ProxyServlet
|
||||
{
|
||||
|
@ -156,64 +148,6 @@ public class ProxyServlet extends AbstractProxyServlet
|
|||
}
|
||||
}
|
||||
|
||||
protected static class TransparentDelegate
|
||||
{
|
||||
private final ProxyServlet proxyServlet;
|
||||
private String _proxyTo;
|
||||
private String _prefix;
|
||||
|
||||
protected TransparentDelegate(ProxyServlet proxyServlet)
|
||||
{
|
||||
this.proxyServlet = proxyServlet;
|
||||
}
|
||||
|
||||
protected void init(ServletConfig config) throws ServletException
|
||||
{
|
||||
_proxyTo = config.getInitParameter("proxyTo");
|
||||
if (_proxyTo == null)
|
||||
throw new UnavailableException("Init parameter 'proxyTo' is required.");
|
||||
|
||||
String prefix = config.getInitParameter("prefix");
|
||||
if (prefix != null)
|
||||
{
|
||||
if (!prefix.startsWith("/"))
|
||||
throw new UnavailableException("Init parameter 'prefix' must start with a '/'.");
|
||||
_prefix = prefix;
|
||||
}
|
||||
|
||||
// Adjust prefix value to account for context path
|
||||
String contextPath = config.getServletContext().getContextPath();
|
||||
_prefix = _prefix == null ? contextPath : (contextPath + _prefix);
|
||||
|
||||
if (proxyServlet._log.isDebugEnabled())
|
||||
proxyServlet._log.debug(config.getServletName() + " @ " + _prefix + " to " + _proxyTo);
|
||||
}
|
||||
|
||||
protected String rewriteTarget(HttpServletRequest request)
|
||||
{
|
||||
String path = request.getRequestURI();
|
||||
if (!path.startsWith(_prefix))
|
||||
return null;
|
||||
|
||||
StringBuilder uri = new StringBuilder(_proxyTo);
|
||||
if (_proxyTo.endsWith("/"))
|
||||
uri.setLength(uri.length() - 1);
|
||||
String rest = path.substring(_prefix.length());
|
||||
if (!rest.startsWith("/"))
|
||||
uri.append("/");
|
||||
uri.append(rest);
|
||||
String query = request.getQueryString();
|
||||
if (query != null)
|
||||
uri.append("?").append(query);
|
||||
URI rewrittenURI = URI.create(uri.toString()).normalize();
|
||||
|
||||
if (!proxyServlet.validateDestination(rewrittenURI.getHost(), rewrittenURI.getPort()))
|
||||
return null;
|
||||
|
||||
return rewrittenURI.toString();
|
||||
}
|
||||
}
|
||||
|
||||
protected class ProxyResponseListener extends Response.Listener.Adapter
|
||||
{
|
||||
private final HttpServletRequest request;
|
||||
|
|
Loading…
Reference in New Issue