com.ibm.sbt.service.basic.ProxyEndpointService.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.sbt.service.basic.ProxyEndpointService.java

Source

/*
 *  Copyright IBM Corp. 2012
 * 
 * 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 com.ibm.sbt.service.basic;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

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

import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreProtocolPNames;

import com.ibm.commons.runtime.Context;
import com.ibm.commons.runtime.RuntimeConstants;
import com.ibm.commons.util.StringUtil;
import com.ibm.sbt.service.core.handlers.ProxyHandler;
import com.ibm.sbt.service.debug.ProxyDebugUtil;
import com.ibm.sbt.services.client.ClientServicesException;
import com.ibm.sbt.services.endpoints.Endpoint;
import com.ibm.sbt.services.endpoints.EndpointFactory;
import com.ibm.sbt.services.util.SSLUtil;

/**
 * Basic proxy using an endpoint.
 * <p>
 * This proxy is using an endpoint name before the actual proxied URL and ensures that
 * the endpoint is defined for the current user. It also checks that the URL parameter is
 * the one defined by the endpoint.<br>
 * Finally, this proxy also ensures that the referer points to the the current server, thus
 * preventing pages without this referer to work.
 * </p>
 * @author Philippe Riand
 */
public class ProxyEndpointService extends ProxyService {

    protected Endpoint endpoint;
    protected String requestURI;

    public ProxyEndpointService() {
    }

    public Endpoint getEndpoint() {
        return endpoint;
    }

    protected String getProxyUrlPath() {
        return ProxyHandler.URL_PATH;
    }

    @Override
    protected boolean isHeaderAllowed(String headerName) throws ServletException {
        // Don't pass the basic authorization as this must be set by the endpoint
        if (StringUtil.equals(headerName, "Authorization")) {
            return false;
        }

        if (!(this.getEndpoint().isHeaderAllowed(headerName, requestURI))) {
            return false;
        }
        // And pass all the other headers
        return super.isHeaderAllowed(headerName);
    }

    @Override
    protected DefaultHttpClient getClient(HttpServletRequest request, int timeout) {
        DefaultHttpClient httpClient = super.getClient(request, timeout);
        if (endpoint != null) {
            if (endpoint.isForceTrustSSLCertificate() && requestURI != null) {
                httpClient = SSLUtil.wrapHttpClient(httpClient);
            }
            if (endpoint.isForceDisableExpectedContinue()) {
                httpClient.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);
            }
            String httpProxy = getHttpProxy(endpoint);
            if (StringUtil.isNotEmpty(httpProxy)) {
                httpClient = ProxyDebugUtil.wrapHttpClient(httpClient, httpProxy);
            }
        }
        return httpClient;
    }

    @Override
    protected void checkRequestAllowed(HttpServletRequest request) throws ServletException {
        if (!isRefererAllowed(request)) {
            throw new ServletException("Invalid request referer");
        }
        super.checkRequestAllowed(request);
    }

    protected boolean isRefererAllowed(HttpServletRequest request) {
        // For now...
        return true;
        //        String referer = request.getHeader("Referer");
        //        if(StringUtil.isNotEmpty(referer)) {
        //            StringBuilder b = new StringBuilder(128);
        //            b.append(request.getScheme());
        //            b.append("://");
        //            b.append(request.getServerName());
        //            int port = request.getServerPort();
        //            b.append(":");
        //            b.append(Integer.toString(port));
        //            b.append(request.getContextPath());
        //            b.append("/");
        //            String url = b.toString();
        //            if(referer.startsWith(url)) {
        //                return true;
        //            }
        //        }
        //        return false;
    }

    @Override
    protected boolean prepareForwardingMethod(HttpRequestBase method, HttpServletRequest request,
            DefaultHttpClient client) throws ServletException {
        boolean ret = super.prepareForwardingMethod(method, request, client);
        initEndpoint(method, request, client, endpoint);
        return ret;
    }

    @Override
    protected boolean forwardCookies(HttpRequestBase method, HttpServletRequest request) {
        return false;
    }

    protected void initEndpoint(HttpRequestBase method, HttpServletRequest request, DefaultHttpClient client,
            Endpoint endpoint) throws ServletException {
        try {
            endpoint.initialize(client);
            endpoint.updateHeaders(client, method);
        } catch (ClientServicesException ex) {
            throw new ServletException(ex);
        }
    }

    @Override
    protected void initProxy(HttpServletRequest request, HttpServletResponse response) throws ServletException {
        String pathInfo = request.getPathInfo();
        // Skip the URL_PATH of the proxy
        //     /[proxy root]/[URL_PATH]/[endpointname]/[full qualified url starting with http] 
        // or
        //     /[proxy root]/[URL_PATH]/[endpointname]/[service url]
        int startEndPoint = getProxyUrlPath().length() + 2;
        if (startEndPoint < pathInfo.length()) {
            int startProxyUrl = pathInfo.indexOf('/', startEndPoint);
            if (startProxyUrl >= 0) {
                String endPointName = pathInfo.substring(startEndPoint, startProxyUrl);
                this.endpoint = EndpointFactory.getEndpoint(endPointName);
                if (!endpoint.isAllowClientAccess()) {
                    throw new ServletException(StringUtil
                            .format("Client access forbidden for the specified endpoint {0}", endPointName));
                }

                String url = null;
                String endpointUrl = endpoint.getUrl();
                if (pathInfo.substring(startProxyUrl + 1).startsWith("http")) {
                    url = pathInfo.substring(startProxyUrl + 1).replaceAll(" ", "%20").replaceFirst("\\/", "://");
                    /*
                       if (!url.startsWith(endpointUrl)) {
                           throw new ServletException(StringUtil.format(
                           "The proxied url does not correspond to the endpoint {0}", endPointName));
                       }
                       */
                } else {
                    pathInfo = pathInfo.substring(startProxyUrl).replaceAll(" ", "%20");
                    url = endpointUrl + pathInfo;
                }
                requestURI = url;
                return;
            }
        }
        StringBuffer b = request.getRequestURL();
        String q = request.getQueryString();
        if (StringUtil.isNotEmpty(q)) {
            b.append('?');
            b.append(q);
        }
        throw new ServletException(StringUtil.format("Invalid url {0}", b.toString()));
    }

    @Override
    protected String getRequestURIPath(HttpServletRequest request) throws ServletException {
        return requestURI;
    }

    public static String getProxyUrlForEndpoint(Context context, String proxyName, String endpointName,
            String url) {
        StringBuilder b = new StringBuilder();
        RuntimeConstants.get().appendBaseProxyUrl(b, context);
        b.append("/");
        b.append(proxyName);
        b.append("/");
        b.append(endpointName);
        if (StringUtil.isNotEmpty(url)) {
            b.append("/");
            String newUrl = url.replaceFirst("://", "\\/");
            b.append(newUrl);
        }
        String proxyUrl = b.toString();
        return proxyUrl;
    }

    @Override
    protected String getRequestURLQueryString(HttpServletRequest request) throws ServletException {
        String queryargs = request.getQueryString();
        String proxyqueryargs = endpoint.getProxyQueryArgs();
        if (proxyqueryargs != null) {
            if (queryargs == null)
                return proxyqueryargs;
            else
                return queryargs + "&" + proxyqueryargs;
        }
        return queryargs;
    }

    /*
     * Return the HttpProxy value if configured
     */
    private String getHttpProxy(Endpoint endpoint) {
        String httpProxy = endpoint.getHttpProxy();
        if (StringUtil.isEmpty(httpProxy)) {
            httpProxy = Context.get().getProperty("sbt.httpProxy");
        }
        return httpProxy;
    }

}