org.hippoecm.frontend.util.RequestUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.hippoecm.frontend.util.RequestUtils.java

Source

/*
 *  Copyright 2015-2016 Hippo B.V. (http://www.onehippo.com)
 *
 *  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.hippoecm.frontend.util;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.ArrayUtils;
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.http.WebRequest;

/**
 * Wicket {@link Request} related utilities.
 */
public class RequestUtils {

    /**
     * Default HTTP Forwarded-For header name. <code>X-Forwarded-For</code> by default.
     */
    public static final String DEFAULT_HTTP_FORWARDED_FOR_HEADER = "X-Forwarded-For";

    /**
     * Servlet context init parameter name for custom HTTP Forwarded-For header name(s).
     * If not set, {@link DEFAULT_HTTP_FORWARDED_FOR_HEADER} is used by default.
     */
    public static final String HTTP_FORWARDED_FOR_HEADER_PARAM = "http-forwarded-for-header";

    /*
     * Package protected for unit tests.
     */
    static String httpForwardedForHeader;

    private RequestUtils() {
    }

    /**
     * Returns the remote client address or null if remote client address information is unavailable.
     * @param request wicket request
     * @return the remote client address or null if remote client address information is unavailable
     */
    public static String getFarthestRemoteAddr(final Request request) {
        String[] remoteAddrs = getRemoteAddrs(request);

        if (ArrayUtils.isNotEmpty(remoteAddrs)) {
            return remoteAddrs[0];
        }

        return null;
    }

    /**
     * Returns the remote host addresses related to this request.
     * If there's any proxy server between the client and the server,
     * then the proxy addresses are contained in the returned array.
     * The lowest indexed element is the farthest downstream client and
     * each successive proxy addresses are the next elements.
     * @param request wicket request
     * @return remote host addresses as non-null string array
     */
    public static String[] getRemoteAddrs(final Request request) {
        if (request instanceof WebRequest) {
            WebRequest webRequest = (WebRequest) request;

            String headerName = getForwardedForHeaderName(webRequest);
            String headerValue = webRequest.getHeader(headerName);

            if (headerValue != null && headerValue.length() > 0) {
                String[] addrs = headerValue.split(",");
                for (int i = 0; i < addrs.length; i++) {
                    addrs[i] = addrs[i].trim();
                }
                return addrs;
            } else if (webRequest.getContainerRequest() instanceof ServletRequest) {
                final ServletRequest servletRequest = (ServletRequest) webRequest.getContainerRequest();
                return new String[] { servletRequest.getRemoteAddr() };
            }
        }

        return ArrayUtils.EMPTY_STRING_ARRAY;
    }

    public static String getFarthestRequestScheme(HttpServletRequest request) {
        String[] schemes = getCommaSeparatedMultipleHeaderValues(request, "X-Forwarded-Proto");

        if (schemes != null && schemes.length != 0) {
            return schemes[0].toLowerCase();
        }

        schemes = getCommaSeparatedMultipleHeaderValues(request, "X-Forwarded-Scheme");

        if (schemes != null && schemes.length != 0) {
            return schemes[0].toLowerCase();
        }

        String[] sslEnabledArray = getCommaSeparatedMultipleHeaderValues(request, "X-SSL-Enabled");

        if (sslEnabledArray == null) {
            sslEnabledArray = getCommaSeparatedMultipleHeaderValues(request, "Front-End-Https");
        }

        if (sslEnabledArray != null && sslEnabledArray.length != 0) {
            String sslEnabled = sslEnabledArray[0];

            if (sslEnabled.equalsIgnoreCase("on") || sslEnabled.equalsIgnoreCase("yes") || sslEnabled.equals("1")) {
                return "https";
            }
        }

        return request.getScheme();
    }

    /**
     * Parse comma separated multiple header value and return an array if the header exists.
     * If the header doesn't exist, it returns null.
     * @param request
     * @param headerName
     * @return null if the header doesn't exist or an array parsed from the comma separated string header value.
     */
    private static String[] getCommaSeparatedMultipleHeaderValues(final HttpServletRequest request,
            final String headerName) {
        String value = request.getHeader(headerName);

        if (value == null) {
            return null;
        }

        String[] tokens = value.split(",");

        for (int i = 0; i < tokens.length; i++) {
            tokens[i] = tokens[i].trim();
        }

        return tokens;
    }

    /**
     * Return <code>X-Forwarded-For</code> HTTP header name by default or custom equivalent HTTP header names
     * if {@link HTTP_FORWARDED_FOR_HEADER} context parameter is defined to use any other custom HTTP header instead.
     * @param request request
     * @return <code>X-Forwarded-For</code> HTTP header name by default or custom equivalent HTTP header name
     */
    private static String getForwardedForHeaderName(final WebRequest request) {
        String forwardedForHeader = httpForwardedForHeader;

        if (forwardedForHeader == null) {
            synchronized (RequestUtils.class) {
                forwardedForHeader = httpForwardedForHeader;

                if (forwardedForHeader == null) {
                    if (request.getContainerRequest() instanceof ServletRequest) {
                        String param = ((ServletRequest) request.getContainerRequest()).getServletContext()
                                .getInitParameter(HTTP_FORWARDED_FOR_HEADER_PARAM);

                        if (param != null) {
                            param = param.trim();

                            if (!param.isEmpty()) {
                                forwardedForHeader = param;
                            }
                        }
                    }

                    if (forwardedForHeader == null) {
                        forwardedForHeader = DEFAULT_HTTP_FORWARDED_FOR_HEADER;
                    }

                    httpForwardedForHeader = forwardedForHeader;
                }
            }
        }

        return forwardedForHeader;
    }

    /**
     * Returns the original host information requested by the client
     * @param request
     * @return the farthest request host
     */
    public static String getFarthestRequestHost(HttpServletRequest request) {
        String host = request.getHeader("X-Forwarded-Host");

        if (host != null) {
            String[] hosts = host.split(",");
            return hosts[0].trim();
        }

        host = request.getHeader("Host");

        if (host != null && !"".equals(host)) {
            return host;
        }

        // fallback to request server name for HTTP/1.0 clients.
        // e.g., HTTP/1.0 based browser clients or load balancer not providing 'Host' header.

        int serverPort = request.getServerPort();

        if (serverPort == 80 || serverPort == 443 || serverPort <= 0) {
            host = request.getServerName();
        } else {
            host = request.getServerName() + ":" + serverPort;
        }

        return host;
    }

    public static String getFarthestUrlPrefix(final Request request) {
        return getFarthestUrlPrefix(((ServletWebRequest) request).getContainerRequest());
    }

    public static String getFarthestUrlPrefix(final HttpServletRequest httpServletRequest) {
        return getFarthestRequestScheme(httpServletRequest) + "://" + getFarthestRequestHost(httpServletRequest);
    }
}