Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  //
  //  ========================================================================
  //  Copyright (c) 1995-2015 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.proxy;
 
 import java.util.Set;
 
 
 public abstract class AbstractProxyServlet extends HttpServlet
 {
     protected static final Set<StringHOP_HEADERS;
     static
     {
         Set<StringhopHeaders = new HashSet<>();
         hopHeaders.add("connection");
         hopHeaders.add("keep-alive");
         hopHeaders.add("proxy-authorization");
         hopHeaders.add("proxy-authenticate");
         hopHeaders.add("proxy-connection");
         hopHeaders.add("transfer-encoding");
         hopHeaders.add("te");
         hopHeaders.add("trailer");
         hopHeaders.add("upgrade");
          = Collections.unmodifiableSet(hopHeaders);
     }
 
     private final Set<String_whiteList = new HashSet<>();
     private final Set<String_blackList = new HashSet<>();
     protected Logger _log;
     private String _hostHeader;
     private String _viaHost;
     private HttpClient _client;
     private long _timeout;
 
     @Override
     public void init() throws ServletException
     {
          = createLogger();
 
         ServletConfig config = getServletConfig();
 
          = config.getInitParameter("hostHeader");
 
          = config.getInitParameter("viaHost");
         if ( == null)
              = viaHost();
 
         try
         {
              = createHttpClient();
 
             // Put the HttpClient in the context to leverage ContextHandler.MANAGED_ATTRIBUTES
             getServletContext().setAttribute(config.getServletName() + ".HttpClient");
 
             String whiteList = config.getInitParameter("whiteList");
             if (whiteList != null)
                 getWhiteListHosts().addAll(parseList(whiteList));
 
            String blackList = config.getInitParameter("blackList");
            if (blackList != null)
                getBlackListHosts().addAll(parseList(blackList));
        }
        catch (Exception e)
        {
            throw new ServletException(e);
        }
    }
    @Override
    public void destroy()
    {
        try
        {
            .stop();
        }
        catch (Exception x)
        {
            if (.isDebugEnabled())
                .debug(x);
        }
    }
    public String getHostHeader()
    {
        return ;
    }
    public String getViaHost()
    {
        return ;
    }
    private static String viaHost()
    {
        try
        {
            return InetAddress.getLocalHost().getHostName();
        }
        catch (UnknownHostException x)
        {
            return "localhost";
        }
    }
    public long getTimeout()
    {
        return ;
    }
    public void setTimeout(long timeout)
    {
        this. = timeout;
    }
    public Set<StringgetWhiteListHosts()
    {
        return ;
    }
    public Set<StringgetBlackListHosts()
    {
        return ;
    }

    

Returns:
a logger instance with a name derived from this servlet's name.
    protected Logger createLogger()
    {
        String servletName = getServletConfig().getServletName();
        servletName = servletName.replace('-''.');
        if ((getClass().getPackage() != null) && !servletName.startsWith(getClass().getPackage().getName()))
        {
            servletName = getClass().getName() + "." + servletName;
        }
        return Log.getLogger(servletName);
    }

    
Creates a org.eclipse.jetty.client.HttpClient instance, configured with init parameters of this servlet.

The init parameters used to configure the org.eclipse.jetty.client.HttpClient instance are:

init-paramdefaultdescription
maxThreads256The max number of threads of HttpClient's Executor. If not set, or set to the value of "-", then the Jetty server thread pool will be used.
maxConnections32768The max number of connections per destination, see org.eclipse.jetty.client.HttpClient.setMaxConnectionsPerDestination(int)
idleTimeout30000The idle timeout in milliseconds, see org.eclipse.jetty.client.HttpClient.setIdleTimeout(long)
timeout60000The total timeout in milliseconds, see org.eclipse.jetty.client.api.Request.timeout(long,java.util.concurrent.TimeUnit)
requestBufferSizeHttpClient's defaultThe request buffer size, see org.eclipse.jetty.client.HttpClient.setRequestBufferSize(int)
responseBufferSizeHttpClient's defaultThe response buffer size, see org.eclipse.jetty.client.HttpClient.setResponseBufferSize(int)

Returns:
a org.eclipse.jetty.client.HttpClient configured from the servlet configuration
Throws:
javax.servlet.ServletException if the org.eclipse.jetty.client.HttpClient cannot be created
    protected HttpClient createHttpClient() throws ServletException
    {
        ServletConfig config = getServletConfig();
        HttpClient client = newHttpClient();
        // Redirects must be proxied as is, not followed
        client.setFollowRedirects(false);
        // Must not store cookies, otherwise cookies of different clients will mix
        client.setCookieStore(new HttpCookieStore.Empty());
        Executor executor;
        String value = config.getInitParameter("maxThreads");
        if (value == null || "-".equals(value))
        {
            executor = (Executor)getServletContext().getAttribute("org.eclipse.jetty.server.Executor");
            if (executor==null)
                throw new IllegalStateException("No server executor for proxy");
        }
        else
        {
            QueuedThreadPool qtpnew QueuedThreadPool(Integer.parseInt(value));
            String servletName = config.getServletName();
            int dot = servletName.lastIndexOf('.');
            if (dot >= 0)
                servletName = servletName.substring(dot + 1);
            qtp.setName(servletName);
            executor=qtp;
        }
        client.setExecutor(executor);
        value = config.getInitParameter("maxConnections");
        if (value == null)
            value = "256";
        client.setMaxConnectionsPerDestination(Integer.parseInt(value));
        value = config.getInitParameter("idleTimeout");
        if (value == null)
            value = "30000";
        client.setIdleTimeout(Long.parseLong(value));
        value = config.getInitParameter("timeout");
        if (value == null)
            value = "60000";
         = Long.parseLong(value);
        value = config.getInitParameter("requestBufferSize");
        if (value != null)
            client.setRequestBufferSize(Integer.parseInt(value));
        value = config.getInitParameter("responseBufferSize");
        if (value != null)
            client.setResponseBufferSize(Integer.parseInt(value));
        try
        {
            client.start();
            // Content must not be decoded, otherwise the client gets confused
            client.getContentDecoderFactories().clear();
            return client;
        }
        catch (Exception x)
        {
            throw new ServletException(x);
        }
    }

    

Returns:
a new HttpClient instance
    protected HttpClient newHttpClient()
    {
        return new HttpClient();
    }
    protected HttpClient getHttpClient()
    {
        return ;
    }
    private Set<StringparseList(String list)
    {
        Set<Stringresult = new HashSet<>();
        String[] hosts = list.split(",");
        for (String host : hosts)
        {
            host = host.trim();
            if (host.length() == 0)
                continue;
            result.add(host);
        }
        return result;
    }

    
Checks the given host and port against whitelist and blacklist.

Parameters:
host the host to check
port the port to check
Returns:
true if it is allowed to be proxy to the given host and port
    public boolean validateDestination(String hostint port)
    {
        String hostPort = host + ":" + port;
        if (!.isEmpty())
        {
            if (!.contains(hostPort))
            {
                if (.isDebugEnabled())
                    .debug("Host {}:{} not whitelisted"hostport);
                return false;
            }
        }
        if (!.isEmpty())
        {
            if (.contains(hostPort))
            {
                if (.isDebugEnabled())
                    .debug("Host {}:{} blacklisted"hostport);
                return false;
            }
        }
        return true;
    }
    protected String rewriteTarget(HttpServletRequest clientRequest)
    {
        if (!validateDestination(clientRequest.getServerName(), clientRequest.getServerPort()))
            return null;
        StringBuffer target = clientRequest.getRequestURL();
        String query = clientRequest.getQueryString();
        if (query != null)
            target.append("?").append(query);
        return target.toString();
    }

    

Callback method invoked when the URI rewrite performed in rewriteTarget(javax.servlet.http.HttpServletRequest) returns null indicating that no rewrite can be performed.

It is possible to use blocking API in this method, like javax.servlet.http.HttpServletResponse.sendError(int).

Parameters:
clientRequest the client request
clientResponse the client response
    protected void onProxyRewriteFailed(HttpServletRequest clientRequestHttpServletResponse clientResponse)
    {
        clientResponse.setStatus(.);
    }
    protected boolean hasContent(HttpServletRequest clientRequest)
    {
        return clientRequest.getContentLength() > 0 ||
                clientRequest.getContentType() != null ||
                clientRequest.getHeader(..asString()) != null;
    }
    protected void copyHeaders(HttpServletRequest clientRequestRequest proxyRequest)
    {
        // First clear possibly existing headers, as we are going to copy those from the client request.
        proxyRequest.getHeaders().clear();
        Set<StringheadersToRemove = findConnectionHeaders(clientRequest);
        for (Enumeration<StringheaderNames = clientRequest.getHeaderNames(); headerNames.hasMoreElements();)
        {
            String headerName = headerNames.nextElement();
            String lowerHeaderName = headerName.toLowerCase(.);
            if (..is(headerName))
                continue;
            // Remove hop-by-hop headers.
            if (.contains(lowerHeaderName))
                continue;
            if (headersToRemove != null && headersToRemove.contains(lowerHeaderName))
                continue;
            for (Enumeration<StringheaderValues = clientRequest.getHeaders(headerName); headerValues.hasMoreElements();)
            {
                String headerValue = headerValues.nextElement();
                if (headerValue != null)
                    proxyRequest.header(headerNameheaderValue);
            }
        }
        // Force the Host header if configured
        if ( != null)
            proxyRequest.header(.);
    }
    protected Set<StringfindConnectionHeaders(HttpServletRequest clientRequest)
    {
        // Any header listed by the Connection header must be removed:
        // http://tools.ietf.org/html/rfc7230#section-6.1.
        Set<StringhopHeaders = null;
        Enumeration<StringconnectionHeaders = clientRequest.getHeaders(..asString());
        while (connectionHeaders.hasMoreElements())
        {
            String value = connectionHeaders.nextElement();
            String[] values = value.split(",");
            for (String name : values)
            {
                name = name.trim().toLowerCase(.);
                if (hopHeaders == null)
                    hopHeaders = new HashSet<>();
                hopHeaders.add(name);
            }
        }
        return hopHeaders;
    }
    protected void addProxyHeaders(HttpServletRequest clientRequestRequest proxyRequest)
    {
        addViaHeader(proxyRequest);
        addXForwardedHeaders(clientRequestproxyRequest);
    }
    protected void addViaHeader(Request proxyRequest)
    {
        proxyRequest.header(."http/1.1 " + getViaHost());
    }
    protected void addXForwardedHeaders(HttpServletRequest clientRequestRequest proxyRequest)
    {
        proxyRequest.header(.clientRequest.getRemoteAddr());
        proxyRequest.header(.clientRequest.getScheme());
        proxyRequest.header(.clientRequest.getHeader(..asString()));
        proxyRequest.header(.clientRequest.getLocalName());
    }
    protected void sendProxyRequest(HttpServletRequest clientRequestHttpServletResponse proxyResponseRequest proxyRequest)
    {
        if (.isDebugEnabled())
        {
            StringBuilder builder = new StringBuilder(clientRequest.getMethod());
            builder.append(" ").append(clientRequest.getRequestURI());
            String query = clientRequest.getQueryString();
            if (query != null)
                builder.append("?").append(query);
            builder.append(" ").append(clientRequest.getProtocol()).append(System.lineSeparator());
            for (Enumeration<StringheaderNames = clientRequest.getHeaderNames(); headerNames.hasMoreElements();)
            {
                String headerName = headerNames.nextElement();
                builder.append(headerName).append(": ");
                for (Enumeration<StringheaderValues = clientRequest.getHeaders(headerName); headerValues.hasMoreElements();)
                {
                    String headerValue = headerValues.nextElement();
                    if (headerValue != null)
                        builder.append(headerValue);
                    if (headerValues.hasMoreElements())
                        builder.append(",");
                }
                builder.append(System.lineSeparator());
            }
            builder.append(System.lineSeparator());
            .debug("{} proxying to upstream:{}{}{}{}",
                    getRequestId(clientRequest),
                    System.lineSeparator(),
                    builder,
                    proxyRequest,
                    System.lineSeparator(),
                    proxyRequest.getHeaders().toString().trim());
        }
        proxyRequest.send(newProxyResponseListener(clientRequestproxyResponse));
    }
    protected abstract Response.CompleteListener newProxyResponseListener(HttpServletRequest clientRequestHttpServletResponse proxyResponse);
    protected void onClientRequestFailure(HttpServletRequest clientRequestRequest proxyRequestHttpServletResponse proxyResponseThrowable failure)
    {
        boolean aborted = proxyRequest.abort(failure);
        if (!aborted)
        {
            proxyResponse.setStatus(500);
            clientRequest.getAsyncContext().complete();
        }
    }
    protected void onServerResponseHeaders(HttpServletRequest clientRequestHttpServletResponse proxyResponseResponse serverResponse)
    {
        for (HttpField field : serverResponse.getHeaders())
        {
            String headerName = field.getName();
            String lowerHeaderName = headerName.toLowerCase(.);
            if (.contains(lowerHeaderName))
                continue;
            String newHeaderValue = filterServerResponseHeader(clientRequestserverResponseheaderNamefield.getValue());
            if (newHeaderValue == null || newHeaderValue.trim().length() == 0)
                continue;
            proxyResponse.addHeader(headerNamenewHeaderValue);
        }
        if (.isDebugEnabled())
        {
            StringBuilder builder = new StringBuilder(System.lineSeparator());
            builder.append(clientRequest.getProtocol()).append(" ").append(proxyResponse.getStatus())
                    .append(" ").append(serverResponse.getReason()).append(System.lineSeparator());
            for (String headerName : proxyResponse.getHeaderNames())
            {
                builder.append(headerName).append(": ");
                for (Iterator<StringheaderValues = proxyResponse.getHeaders(headerName).iterator(); headerValues.hasNext(); )
                {
                    String headerValue = headerValues.next();
                    if (headerValue != null)
                        builder.append(headerValue);
                    if (headerValues.hasNext())
                        builder.append(",");
                }
                builder.append(System.lineSeparator());
            }
            .debug("{} proxying to downstream:{}{}{}{}{}",
                    getRequestId(clientRequest),
                    System.lineSeparator(),
                    serverResponse,
                    System.lineSeparator(),
                    serverResponse.getHeaders().toString().trim(),
                    System.lineSeparator(),
                    builder);
        }
    }
    protected String filterServerResponseHeader(HttpServletRequest clientRequestResponse serverResponseString headerNameString headerValue)
    {
        return headerValue;
    }
    protected void onProxyResponseSuccess(HttpServletRequest clientRequestHttpServletResponse proxyResponseResponse serverResponse)
    {
        if (.isDebugEnabled())
            .debug("{} proxying successful"getRequestId(clientRequest));
        AsyncContext asyncContext = clientRequest.getAsyncContext();
        asyncContext.complete();
    }
    protected void onProxyResponseFailure(HttpServletRequest clientRequestHttpServletResponse proxyResponseResponse serverResponseThrowable failure)
    {
        if (.isDebugEnabled())
            .debug(getRequestId(clientRequest) + " proxying failed"failure);
        if (proxyResponse.isCommitted())
        {
            try
            {
                // Use Jetty specific behavior to close connection.
                proxyResponse.sendError(-1);
                AsyncContext asyncContext = clientRequest.getAsyncContext();
                asyncContext.complete();
            }
            catch (IOException x)
            {
                if (.isDebugEnabled())
                    .debug(getRequestId(clientRequest) + " could not close the connection"failure);
            }
        }
        else
        {
            proxyResponse.resetBuffer();
            if (failure instanceof TimeoutException)
                proxyResponse.setStatus(.);
            else
                proxyResponse.setStatus(.);
            proxyResponse.setHeader(..asString(), ..asString());
            AsyncContext asyncContext = clientRequest.getAsyncContext();
            asyncContext.complete();
        }
    }
    protected int getRequestId(HttpServletRequest clientRequest)
    {
        return System.identityHashCode(clientRequest);
    }
New to GrepCode? Check out our FAQ X