org.overlord.gadgets.web.server.servlets.RestProxyServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.overlord.gadgets.web.server.servlets.RestProxyServlet.java

Source

/*
 * Copyright 2013 JBoss Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.overlord.gadgets.web.server.servlets;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.List;
import java.util.Map.Entry;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.overlord.gadgets.server.ConfiguredModule;

/**
 * A simple proxy servlet for REST invokations.  The primary purpose of this servlet is
 * to provide a way to inject appropriate authentication mechanisms when invoking a
 * protected REST service directly from the Browser.  When that is impossible (because
 * the browser does not have the appropriate credentials available to it) then the
 * browser can invoke this servlet instead.  This servlet will in turn invoke the
 * protected REST service and proxy the response.
 *
 * @author eric.wittmann@redhat.com
 */
public class RestProxyServlet extends HttpServlet {

    private static final long serialVersionUID = 8689929059530563599L;

    private String proxyName;
    private String proxyUrl;
    private String authProviderClassName;

    /**
     * Constructor.
     */
    public RestProxyServlet() {
    }

    /**
     * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        proxyName = config.getInitParameter("proxy-name");
        if (proxyName == null)
            throw new ServletException("Missing init parameter 'proxy-name'.");

        proxyUrl = config.getInitParameter("proxy-url");
        if (proxyUrl == null)
            throw new ServletException("Missing init parameter 'proxy-url'.");

        authProviderClassName = config.getInitParameter("authentication-provider");
    }

    /**
     * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Proxy inbound endpoint: " + req.getRequestURI());
        // Connect to proxy URL.
        String urlStr = getProxyUrl(req);
        String queryString = req.getQueryString();
        if (queryString != null) {
            urlStr = urlStr + "?" + queryString;
        }
        System.out.println("Proxying to: " + urlStr);
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");

        // Proxy all of the request headers.
        Enumeration<?> headerNames = req.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = String.valueOf(headerNames.nextElement());
            Enumeration<?> headerValues = req.getHeaders(headerName);
            while (headerValues.hasMoreElements()) {
                String headerValue = String.valueOf(headerValues.nextElement());
                conn.addRequestProperty(headerName, headerValue);
            }
        }

        // Handle authentication
        RestProxyAuthProvider authProvider = getAuthProvider();
        if (authProvider != null) {
            authProvider.provideAuthentication(conn);
        }

        // Now connect and proxy the response.
        InputStream proxyUrlResponseStream = null;
        try {
            proxyUrlResponseStream = conn.getInputStream();
            resp.setStatus(conn.getResponseCode());
            // Proxy the response headers
            for (Entry<String, List<String>> entry : conn.getHeaderFields().entrySet()) {
                String respHeaderName = entry.getKey();
                if (respHeaderName != null && !respHeaderName.equalsIgnoreCase("transfer-encoding")) {
                    for (String respHeaderValue : entry.getValue()) {
                        resp.addHeader(respHeaderName, respHeaderValue);
                    }
                }
            }

            // Proxy the response body.
            IOUtils.copy(proxyUrlResponseStream, resp.getOutputStream());
        } finally {
            IOUtils.closeQuietly(proxyUrlResponseStream);
            conn.disconnect();
        }
    }

    /**
     * @param req the inbound http request
     * @return the proxy url, with property substitutions
     */
    private String getProxyUrl(HttpServletRequest req) {
        String scheme = req.getScheme();
        String host = req.getServerName();
        String port = String.valueOf(req.getServerPort());
        return this.proxyUrl.replace("SCHEME", scheme).replace("HOST", host).replace("PORT", port);
    }

    /**
     * Gets the authentication provider.  This will look up the auth provider to used either from a
     * servlet init param or from the configuration properties.
     */
    private RestProxyAuthProvider getAuthProvider() throws ServletException {
        String classname = authProviderClassName;
        if (classname == null) {
            classname = ConfiguredModule.properties
                    .getProperty("gadget-server.rest-proxy." + proxyName + ".authentication-provider");
        }
        if (classname != null) {
            try {
                Class<?> authProviderClass = Class.forName(classname);
                RestProxyAuthProvider authProvider = (RestProxyAuthProvider) authProviderClass.newInstance();
                authProvider.setConfiguration(proxyName, ConfiguredModule.properties);
                return authProvider;
            } catch (Exception e) {
                throw new ServletException(e);
            }
        }

        return null;
    }

}