You are viewing a plain text version of this content. The canonical link for it is here.
Posted to portalapps-dev@portals.apache.org by wo...@apache.org on 2015/01/03 21:05:56 UTC

svn commit: r1649240 - in /portals/applications/webcontent/trunk: portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/ reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/ reverse-proxy/src/main/ja...

Author: woonsan
Date: Sat Jan  3 20:05:55 2015
New Revision: 1649240

URL: http://svn.apache.org/r1649240
Log:
APA-71: supporting https in reverse-proxy
- supporting scheme-less remote URI request
- ssl socket connection factory initialization

Added:
    portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/SimpleProxyMappingTest.java
    portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples1/
    portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples1/mission.html
    portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples1/redirection.jsp
    portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples2/
    portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples2/mission.html
    portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples2/redirection.jsp
Modified:
    portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/PortletRequestContext.java
    portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/SimpleReverseProxyPortlet.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/RequestContext.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/command/ResolveRemoteURICommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/filter/SimpleReverseProxyFilter.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/ServletRequestContext.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/SimpleProxyMapping.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/servlet/SimpleReverseProxyServlet.java
    portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/RegexProxyMappingTest.java
    portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/WEB-INF/rproxy-mappings.yaml
    portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/WEB-INF/web.xml
    portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/index.jsp
    portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/portlet.xml
    portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/rproxy-mappings.yaml
    portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/web.xml

Modified: portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/PortletRequestContext.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/PortletRequestContext.java?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/PortletRequestContext.java (original)
+++ portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/PortletRequestContext.java Sat Jan  3 20:05:55 2015
@@ -105,6 +105,14 @@ public class PortletRequestContext imple
     /**
      * {@inheritDoc}
      */
+    public String getScheme()
+    {
+        return request.getScheme();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     public String getServerName()
     {
         return request.getServerName();

Modified: portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/SimpleReverseProxyPortlet.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/SimpleReverseProxyPortlet.java?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/SimpleReverseProxyPortlet.java (original)
+++ portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/SimpleReverseProxyPortlet.java Sat Jan  3 20:05:55 2015
@@ -27,6 +27,10 @@ import javax.portlet.PortletException;
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang.BooleanUtils;
 import org.apache.commons.lang.StringUtils;
+import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLContexts;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
 import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.portals.applications.webcontent2.proxy.HttpClientContextBuilder;
@@ -95,6 +99,16 @@ public class SimpleReverseProxyPortlet e
     private HttpClientContextBuilder httpClientContextBuilder;
 
     /**
+     * SSL Socket Connection Factory.
+     */
+    private LayeredConnectionSocketFactory sslSocketFactory;
+
+    /**
+     * SSL Hostname Verifier.
+     */
+    private X509HostnameVerifier hostnameVerifier = SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
+
+    /**
      * Internal root reverse proxy processing chain instance.
      */
     private ProxyProcessingChain proxyServiceCommand;
@@ -114,6 +128,7 @@ public class SimpleReverseProxyPortlet e
     public void init(PortletConfig portletConfig) throws PortletException
     {
         super.init(portletConfig);
+        initHostnameVerifier(portletConfig);
 
         proxyServiceCommand = createProxyServiceCommand();
         ProxyCommandUtils.initializeAllCommands(proxyServiceCommand);
@@ -123,6 +138,35 @@ public class SimpleReverseProxyPortlet e
     }
 
     /**
+     * Initializes SSL hostnameVerifier (type of {@link X509HostnameVerifier})
+     * from the init parameter, "ssl-hostname-verifier".
+     * <p>
+     * The init parameter can be any of "ALLOW_ALL_HOSTNAME_VERIFIER", "BROWSER_COMPATIBLE_HOSTNAME_VERIFIER"
+     * or "STRICT_HOSTNAME_VERIFIER", case-insensitively. The default value is "BROWSER_COMPATIBLE_HOSTNAME_VERIFIER".
+     * </p>
+     * @param servletConfig
+     */
+    protected void initHostnameVerifier(PortletConfig portletConfig) {
+        String param = StringUtils.trim(portletConfig.getInitParameter("ssl-hostname-verifier"));
+
+        if (StringUtils.isNotEmpty(param))
+        {
+            if (StringUtils.equalsIgnoreCase("ALLOW_ALL_HOSTNAME_VERIFIER", param))
+            {
+                setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+            }
+            else if (StringUtils.equalsIgnoreCase("BROWSER_COMPATIBLE_HOSTNAME_VERIFIER", param))
+            {
+                setHostnameVerifier(SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+            }
+            else if (StringUtils.equalsIgnoreCase("STRICT_HOSTNAME_VERIFIER", param))
+            {
+                setHostnameVerifier(SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER);
+            }
+        }
+    }
+
+    /**
      * Returns the internal {@link ProxyMappingRegistry} instance.
      * @return
      */
@@ -154,7 +198,7 @@ public class SimpleReverseProxyPortlet e
     {
         if (httpClientBuilder == null)
         {
-            httpClientBuilder = HttpClients.custom();
+            httpClientBuilder = createHttpClientBuilder();
         }
 
         return httpClientBuilder;
@@ -188,6 +232,48 @@ public class SimpleReverseProxyPortlet e
     }
 
     /**
+     * Returns the internal SSL Socket Connection Factory ({@link LayeredConnectionSocketFactory}).
+     * If not set, it invokes {@link #createSslSocketFactory()} to create a default one.
+     * @return
+     */
+    public LayeredConnectionSocketFactory getSslSocketFactory()
+    {
+        if (sslSocketFactory == null)
+        {
+            sslSocketFactory = createSslSocketFactory();
+        }
+
+        return sslSocketFactory;
+    }
+
+    /**
+     * Sets the internal SSL Socket Connection Factory ({@link LayeredConnectionSocketFactory}).
+     * @param sslSocketFactory
+     */
+    public void setSslSocketFactory(LayeredConnectionSocketFactory sslSocketFactory)
+    {
+        this.sslSocketFactory = sslSocketFactory;
+    }
+
+    /**
+     * Returns the internal SSL Hostname Verifier.
+     * @return
+     */
+    public X509HostnameVerifier getHostnameVerifier()
+    {
+        return hostnameVerifier;
+    }
+
+    /**
+     * Sets the internal SSL Hostname Verifier.
+     * @param hostnameVerifier
+     */
+    public void setHostnameVerifier(X509HostnameVerifier hostnameVerifier)
+    {
+        this.hostnameVerifier = hostnameVerifier;
+    }
+
+    /**
      * {@inheritDoc}
      */
     @Override
@@ -322,4 +408,32 @@ public class SimpleReverseProxyPortlet e
         visitors.add(new DefaultPortletProxyTagNodeVisitor());
         return visitors;
     }
+
+    /**
+     * Creates {@link HttpClientBuilder} instance.
+     * This method is invoked by {@link #getHttpClientBuilder()}
+     * if an {@link HttpClientBuilder} instance was not set before.
+     * @return
+     */
+    protected HttpClientBuilder createHttpClientBuilder() {
+        HttpClientBuilder builder = HttpClients.custom().useSystemProperties();
+
+        LayeredConnectionSocketFactory sslSocketFactory = getSslSocketFactory();
+
+        if (sslSocketFactory != null)
+        {
+            builder.setSSLSocketFactory(sslSocketFactory);
+        }
+
+        return builder;
+    }
+
+    /**
+     * Creates the default internal SSL Socket Connection Factory ({@link LayeredConnectionSocketFactory}).
+     * @return
+     */
+    protected LayeredConnectionSocketFactory createSslSocketFactory()
+    {
+        return new SSLConnectionSocketFactory(SSLContexts.createDefault(), getHostnameVerifier());
+    }
 }

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/RequestContext.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/RequestContext.java?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/RequestContext.java (original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/RequestContext.java Sat Jan  3 20:05:55 2015
@@ -46,6 +46,14 @@ public interface RequestContext
     public boolean isSecure();
 
     /**
+     * Returns the scheme of the request URI.
+     * @return
+     * @see {@link javax.servlet.ServletRequest#getScheme()}
+     * @see {@link javax.portlet.PortletRequest#getScheme()}.
+     */
+    public String getScheme();
+
+    /**
      * Returns the host name of the server to which the request was sent.
      * It is the value of the part before ":" in the Host header value, if any, or
      * the resolved server name, or the server IP address.

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/command/ResolveRemoteURICommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/command/ResolveRemoteURICommand.java?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/command/ResolveRemoteURICommand.java (original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/command/ResolveRemoteURICommand.java Sat Jan  3 20:05:55 2015
@@ -60,6 +60,13 @@ public class ResolveRemoteURICommand ext
             throw new ReverseProxyException(HttpServletResponse.SC_NOT_FOUND, "No mapped URI.");
         }
 
+        // resolve the scheme for scheme-less URI.
+        if (remoteURI.startsWith("//"))
+        {
+            final String defaultScheme = getDefaultScheme(context);
+            remoteURI = new StringBuilder(remoteURI.length() + 6).append(defaultScheme).append(':').append(remoteURI).toString();
+        }
+
         String queryString = context.getRequestContext().getQueryString();
 
         if (queryString != null)
@@ -109,4 +116,13 @@ public class ResolveRemoteURICommand ext
         this.uriCleaner = uriCleaner;
     }
 
+    /**
+     * Finds the default scheme ("http" or "https") when a scheme-less remote URI was requested.
+     * @param context
+     * @return
+     */
+    protected String getDefaultScheme(final ProxyContext context)
+    {
+        return context.getRequestContext().getScheme();
+    }
 }

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/filter/SimpleReverseProxyFilter.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/filter/SimpleReverseProxyFilter.java?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/filter/SimpleReverseProxyFilter.java (original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/filter/SimpleReverseProxyFilter.java Sat Jan  3 20:05:55 2015
@@ -21,6 +21,11 @@ import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
 
 import org.apache.commons.chain.Command;
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLContexts;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
 import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.portals.applications.webcontent2.proxy.HttpClientContextBuilder;
@@ -39,11 +44,39 @@ import org.apache.portals.applications.w
 public class SimpleReverseProxyFilter extends GenericReverseProxyFilter
 {
 
+    /**
+     * Reverse proxy mapping initialization parameter name.
+     */
     public static final String MAPPINGS_PARAM_NAME = "mappings";
 
+    /**
+     * Internal reverse proxy mapping registry.
+     */
     private ProxyMappingRegistry proxyMappingRegistry;
+
+    /**
+     * Internal {@link HttpClientBuilder} instance.
+     */
     private HttpClientBuilder httpClientBuilder;
+
+    /**
+     * Internal {@link HttpClientContextBuilder} instance.
+     */
     private HttpClientContextBuilder httpClientContextBuilder;
+
+    /**
+     * SSL Socket Connection Factory.
+     */
+    private LayeredConnectionSocketFactory sslSocketFactory;
+
+    /**
+     * SSL Hostname Verifier.
+     */
+    private X509HostnameVerifier hostnameVerifier = SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
+
+    /**
+     * Internal root reverse proxy processing chain instance.
+     */
     private ProxyProcessingChain proxyServiceCommand;
 
     /**
@@ -62,6 +95,7 @@ public class SimpleReverseProxyFilter ex
     public void init(FilterConfig filterConfig) throws ServletException
     {
         super.init(filterConfig);
+        initHostnameVerifier(filterConfig);
 
         proxyServiceCommand = createProxyServiceCommand();
         ProxyCommandUtils.initializeAllCommands(proxyServiceCommand);
@@ -71,6 +105,35 @@ public class SimpleReverseProxyFilter ex
     }
 
     /**
+     * Initializes SSL hostnameVerifier (type of {@link X509HostnameVerifier})
+     * from the init parameter, "ssl-hostname-verifier".
+     * <p>
+     * The init parameter can be any of "ALLOW_ALL_HOSTNAME_VERIFIER", "BROWSER_COMPATIBLE_HOSTNAME_VERIFIER"
+     * or "STRICT_HOSTNAME_VERIFIER", case-insensitively. The default value is "BROWSER_COMPATIBLE_HOSTNAME_VERIFIER".
+     * </p>
+     * @param filterConfig
+     */
+    protected void initHostnameVerifier(FilterConfig filterConfig) {
+        String param = StringUtils.trim(filterConfig.getInitParameter("ssl-hostname-verifier"));
+
+        if (StringUtils.isNotEmpty(param))
+        {
+            if (StringUtils.equalsIgnoreCase("ALLOW_ALL_HOSTNAME_VERIFIER", param))
+            {
+                setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+            }
+            else if (StringUtils.equalsIgnoreCase("BROWSER_COMPATIBLE_HOSTNAME_VERIFIER", param))
+            {
+                setHostnameVerifier(SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+            }
+            else if (StringUtils.equalsIgnoreCase("STRICT_HOSTNAME_VERIFIER", param))
+            {
+                setHostnameVerifier(SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER);
+            }
+        }
+    }
+
+    /**
      * Returns the internal {@link ProxyMappingRegistry} instance.
      * @return
      */
@@ -104,7 +167,7 @@ public class SimpleReverseProxyFilter ex
     {
         if (httpClientBuilder == null)
         {
-            return HttpClients.custom().disableRedirectHandling();
+            httpClientBuilder = createHttpClientBuilder();
         }
 
         return httpClientBuilder;
@@ -138,6 +201,48 @@ public class SimpleReverseProxyFilter ex
     }
 
     /**
+     * Returns the internal SSL Socket Connection Factory ({@link LayeredConnectionSocketFactory}).
+     * If not set, it invokes {@link #createSslSocketFactory()} to create a default one.
+     * @return
+     */
+    public LayeredConnectionSocketFactory getSslSocketFactory()
+    {
+        if (sslSocketFactory == null)
+        {
+            sslSocketFactory = createSslSocketFactory();
+        }
+
+        return sslSocketFactory;
+    }
+
+    /**
+     * Sets the internal SSL Socket Connection Factory ({@link LayeredConnectionSocketFactory}).
+     * @param sslSocketFactory
+     */
+    public void setSslSocketFactory(LayeredConnectionSocketFactory sslSocketFactory)
+    {
+        this.sslSocketFactory = sslSocketFactory;
+    }
+
+    /**
+     * Returns the internal SSL Hostname Verifier.
+     * @return
+     */
+    public X509HostnameVerifier getHostnameVerifier()
+    {
+        return hostnameVerifier;
+    }
+
+    /**
+     * Sets the internal SSL Hostname Verifier.
+     * @param hostnameVerifier
+     */
+    public void setHostnameVerifier(X509HostnameVerifier hostnameVerifier)
+    {
+        this.hostnameVerifier = hostnameVerifier;
+    }
+
+    /**
      * Disposes all the {@link Command}s in the root reverse proxy processing chain.
      */
     @Override
@@ -155,4 +260,32 @@ public class SimpleReverseProxyFilter ex
     protected ProxyProcessingChain createProxyServiceCommand() {
         return ProxyServices.createDefault().build(getProxyMappingRegistry(), getHttpClientBuilder(), getHttpClientContextBuilder());
     }
+
+    /**
+     * Creates {@link HttpClientBuilder} instance.
+     * This method is invoked by {@link #getHttpClientBuilder()}
+     * if an {@link HttpClientBuilder} instance was not set before.
+     * @return
+     */
+    protected HttpClientBuilder createHttpClientBuilder() {
+        HttpClientBuilder builder = HttpClients.custom().disableRedirectHandling().useSystemProperties();
+
+        LayeredConnectionSocketFactory sslSocketFactory = getSslSocketFactory();
+
+        if (sslSocketFactory != null)
+        {
+            builder.setSSLSocketFactory(sslSocketFactory);
+        }
+
+        return builder;
+    }
+
+    /**
+     * Creates the default internal SSL Socket Connection Factory ({@link LayeredConnectionSocketFactory}).
+     * @return
+     */
+    protected LayeredConnectionSocketFactory createSslSocketFactory()
+    {
+        return new SSLConnectionSocketFactory(SSLContexts.createDefault(), getHostnameVerifier());
+    }
 }

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/ServletRequestContext.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/ServletRequestContext.java?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/ServletRequestContext.java (original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/ServletRequestContext.java Sat Jan  3 20:05:55 2015
@@ -100,6 +100,14 @@ public class ServletRequestContext imple
     /**
      * {@inheritDoc}
      */
+    public String getScheme()
+    {
+        return request.getScheme();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     public String getServerName()
     {
         return request.getServerName();

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/SimpleProxyMapping.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/SimpleProxyMapping.java?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/SimpleProxyMapping.java (original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/SimpleProxyMapping.java Sat Jan  3 20:05:55 2015
@@ -112,7 +112,14 @@ public class SimpleProxyMapping extends
      */
     public boolean matchesRemote(URI remoteURI)
     {
-        return StringUtils.startsWith(remoteURI.toString(), remoteBaseURI.toString());
+        String remoteURIString = remoteURI.toString();
+
+        if (remoteBaseURI.getScheme() == null && remoteURI.getScheme() != null)
+        {
+            remoteURIString = remoteURIString.substring(remoteURI.getScheme().length() + 1);
+        }
+
+        return StringUtils.startsWith(remoteURIString, remoteBaseURI.toString());
     }
 
     /**
@@ -122,7 +129,7 @@ public class SimpleProxyMapping extends
     {
         if (matchesRemote(remoteURI))
         {
-            return localBasePath + remoteURI.toString().substring(remoteBaseURI.toString().length());
+            return localBasePath + StringUtils.substringAfter(remoteURI.toString(), remoteBaseURI.toString());
         }
 
         return null;

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/servlet/SimpleReverseProxyServlet.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/servlet/SimpleReverseProxyServlet.java?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/servlet/SimpleReverseProxyServlet.java (original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/servlet/SimpleReverseProxyServlet.java Sat Jan  3 20:05:55 2015
@@ -20,6 +20,11 @@ import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
 
 import org.apache.commons.chain.Command;
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLContexts;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
 import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.portals.applications.webcontent2.proxy.HttpClientContextBuilder;
@@ -60,6 +65,16 @@ public class SimpleReverseProxyServlet e
     private HttpClientContextBuilder httpClientContextBuilder;
 
     /**
+     * SSL Socket Connection Factory.
+     */
+    private LayeredConnectionSocketFactory sslSocketFactory;
+
+    /**
+     * SSL Hostname Verifier.
+     */
+    private X509HostnameVerifier hostnameVerifier = SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
+
+    /**
      * Internal root reverse proxy processing chain instance.
      */
     private ProxyProcessingChain proxyServiceCommand;
@@ -80,6 +95,7 @@ public class SimpleReverseProxyServlet e
     public void init(ServletConfig servletConfig) throws ServletException
     {
         super.init(servletConfig);
+        initHostnameVerifier(servletConfig);
 
         proxyServiceCommand = createProxyServiceCommand();
         ProxyCommandUtils.initializeAllCommands(proxyServiceCommand);
@@ -89,6 +105,35 @@ public class SimpleReverseProxyServlet e
     }
 
     /**
+     * Initializes SSL hostnameVerifier (type of {@link X509HostnameVerifier})
+     * from the init parameter, "ssl-hostname-verifier".
+     * <p>
+     * The init parameter can be any of "ALLOW_ALL_HOSTNAME_VERIFIER", "BROWSER_COMPATIBLE_HOSTNAME_VERIFIER"
+     * or "STRICT_HOSTNAME_VERIFIER", case-insensitively. The default value is "BROWSER_COMPATIBLE_HOSTNAME_VERIFIER".
+     * </p>
+     * @param servletConfig
+     */
+    protected void initHostnameVerifier(ServletConfig servletConfig) {
+        String param = StringUtils.trim(servletConfig.getInitParameter("ssl-hostname-verifier"));
+
+        if (StringUtils.isNotEmpty(param))
+        {
+            if (StringUtils.equalsIgnoreCase("ALLOW_ALL_HOSTNAME_VERIFIER", param))
+            {
+                setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+            }
+            else if (StringUtils.equalsIgnoreCase("BROWSER_COMPATIBLE_HOSTNAME_VERIFIER", param))
+            {
+                setHostnameVerifier(SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+            }
+            else if (StringUtils.equalsIgnoreCase("STRICT_HOSTNAME_VERIFIER", param))
+            {
+                setHostnameVerifier(SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER);
+            }
+        }
+    }
+
+    /**
      * Returns the internal {@link ProxyMappingRegistry} instance.
      * @return
      */
@@ -122,7 +167,7 @@ public class SimpleReverseProxyServlet e
     {
         if (httpClientBuilder == null)
         {
-            return HttpClients.custom().disableRedirectHandling();
+            httpClientBuilder = createHttpClientBuilder();
         }
 
         return httpClientBuilder;
@@ -156,6 +201,48 @@ public class SimpleReverseProxyServlet e
     }
 
     /**
+     * Returns the internal SSL Socket Connection Factory ({@link LayeredConnectionSocketFactory}).
+     * If not set, it invokes {@link #createSslSocketFactory()} to create a default one.
+     * @return
+     */
+    public LayeredConnectionSocketFactory getSslSocketFactory()
+    {
+        if (sslSocketFactory == null)
+        {
+            sslSocketFactory = createSslSocketFactory();
+        }
+
+        return sslSocketFactory;
+    }
+
+    /**
+     * Sets the internal SSL Socket Connection Factory ({@link LayeredConnectionSocketFactory}).
+     * @param sslSocketFactory
+     */
+    public void setSslSocketFactory(LayeredConnectionSocketFactory sslSocketFactory)
+    {
+        this.sslSocketFactory = sslSocketFactory;
+    }
+
+    /**
+     * Returns the internal SSL Hostname Verifier.
+     * @return
+     */
+    public X509HostnameVerifier getHostnameVerifier()
+    {
+        return hostnameVerifier;
+    }
+
+    /**
+     * Sets the internal SSL Hostname Verifier.
+     * @param hostnameVerifier
+     */
+    public void setHostnameVerifier(X509HostnameVerifier hostnameVerifier)
+    {
+        this.hostnameVerifier = hostnameVerifier;
+    }
+
+    /**
      * Disposes all the {@link Command}s in the root reverse proxy processing chain.
      */
     @Override
@@ -173,4 +260,32 @@ public class SimpleReverseProxyServlet e
     protected ProxyProcessingChain createProxyServiceCommand() {
         return ProxyServices.createDefault().build(getProxyMappingRegistry(), getHttpClientBuilder(), getHttpClientContextBuilder());
     }
+
+    /**
+     * Creates {@link HttpClientBuilder} instance.
+     * This method is invoked by {@link #getHttpClientBuilder()}
+     * if an {@link HttpClientBuilder} instance was not set before.
+     * @return
+     */
+    protected HttpClientBuilder createHttpClientBuilder() {
+        HttpClientBuilder builder = HttpClients.custom().disableRedirectHandling().useSystemProperties();
+
+        LayeredConnectionSocketFactory sslSocketFactory = getSslSocketFactory();
+
+        if (sslSocketFactory != null)
+        {
+            builder.setSSLSocketFactory(sslSocketFactory);
+        }
+
+        return builder;
+    }
+
+    /**
+     * Creates the default internal SSL Socket Connection Factory ({@link LayeredConnectionSocketFactory}).
+     * @return
+     */
+    protected LayeredConnectionSocketFactory createSslSocketFactory()
+    {
+        return new SSLConnectionSocketFactory(SSLContexts.createDefault(), getHostnameVerifier());
+    }
 }

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/RegexProxyMappingTest.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/RegexProxyMappingTest.java?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/RegexProxyMappingTest.java (original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/RegexProxyMappingTest.java Sat Jan  3 20:05:55 2015
@@ -39,6 +39,9 @@ public class RegexProxyMappingTest
         assertTrue(mapping.matchesLocal("/apache/portals/"));
         assertTrue(mapping.matchesLocal("/apache/portals/mission.html"));
 
+        assertTrue(mapping.matchesRemote(URI.create("http://portals.apache.org/")));
+        assertTrue(mapping.matchesRemote(URI.create("http://portals.apache.org/mission.html")));
+
         assertEquals("http://portals.apache.org/", mapping.resolveRemoteFromLocal("/apache/portals/"));
         assertEquals("http://portals.apache.org/mission.html", mapping.resolveRemoteFromLocal("/apache/portals/mission.html"));
 
@@ -46,4 +49,26 @@ public class RegexProxyMappingTest
         assertEquals("/apache/portals/mission.html", mapping.resolveLocalFromRemote(URI.create("http://portals.apache.org/mission.html")));
     }
 
+    @Test
+    public void testRegexMappingsWithoutScheme() throws Exception
+    {
+        RegexProxyMapping mapping = new RegexProxyMapping();
+
+        mapping.setLocalPattern("^/apache/(\\w+)/(.*)$");
+        mapping.setRemoteReplace("//$1.apache.org/$2");
+        mapping.setRemotePattern("^https?://(\\w+)\\.apache\\.org/(.*)$");
+        mapping.setLocalReplace("/apache/$1/$2");
+
+        assertTrue(mapping.matchesLocal("/apache/portals/"));
+        assertTrue(mapping.matchesLocal("/apache/portals/mission.html"));
+
+        assertTrue(mapping.matchesRemote(URI.create("http://portals.apache.org/")));
+        assertTrue(mapping.matchesRemote(URI.create("http://portals.apache.org/mission.html")));
+
+        assertEquals("//portals.apache.org/", mapping.resolveRemoteFromLocal("/apache/portals/"));
+        assertEquals("//portals.apache.org/mission.html", mapping.resolveRemoteFromLocal("/apache/portals/mission.html"));
+
+        assertEquals("/apache/portals/", mapping.resolveLocalFromRemote(URI.create("http://portals.apache.org/")));
+        assertEquals("/apache/portals/mission.html", mapping.resolveLocalFromRemote(URI.create("http://portals.apache.org/mission.html")));
+    }
 }

Added: portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/SimpleProxyMappingTest.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/SimpleProxyMappingTest.java?rev=1649240&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/SimpleProxyMappingTest.java (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/SimpleProxyMappingTest.java Sat Jan  3 20:05:55 2015
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.portals.applications.webcontent2.proxy.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.net.URI;
+
+import org.junit.Test;
+
+public class SimpleProxyMappingTest
+{
+
+    @Test
+    public void testSimpleMappings() throws Exception
+    {
+        SimpleProxyMapping mapping = new SimpleProxyMapping();
+        mapping.setLocal("/portals/applications/");
+        mapping.setRemote(URI.create("http://portals.apache.org/applications/"));
+
+        assertTrue(mapping.matchesLocal("/portals/applications/"));
+        assertTrue(mapping.matchesLocal("/portals/applications/webcontent2/index.html"));
+
+        assertTrue(mapping.matchesRemote(URI.create("http://portals.apache.org/applications/")));
+        assertTrue(mapping.matchesRemote(URI.create("http://portals.apache.org/applications/webcontent2/index.html")));
+
+        assertEquals("http://portals.apache.org/applications/", mapping.resolveRemoteFromLocal("/portals/applications/"));
+        assertEquals("http://portals.apache.org/applications/webcontent2/index.html", mapping.resolveRemoteFromLocal("/portals/applications/webcontent2/index.html"));
+
+        assertEquals("/portals/applications/", mapping.resolveLocalFromRemote(URI.create("http://portals.apache.org/applications/")));
+        assertEquals("/portals/applications/webcontent2/index.html", mapping.resolveLocalFromRemote(URI.create("http://portals.apache.org/applications/webcontent2/index.html")));
+    }
+
+    @Test
+    public void testSimpleMappingsWithoutScheme() throws Exception
+    {
+        SimpleProxyMapping mapping = new SimpleProxyMapping();
+        mapping.setLocal("/portals/applications/");
+        mapping.setRemote(URI.create("//portals.apache.org/applications/"));
+
+        assertTrue(mapping.matchesLocal("/portals/applications/"));
+        assertTrue(mapping.matchesLocal("/portals/applications/webcontent2/index.html"));
+
+        assertTrue(mapping.matchesRemote(URI.create("http://portals.apache.org/applications/")));
+        assertTrue(mapping.matchesRemote(URI.create("http://portals.apache.org/applications/webcontent2/index.html")));
+
+        assertEquals("//portals.apache.org/applications/", mapping.resolveRemoteFromLocal("/portals/applications/"));
+        assertEquals("//portals.apache.org/applications/webcontent2/index.html", mapping.resolveRemoteFromLocal("/portals/applications/webcontent2/index.html"));
+
+        assertEquals("/portals/applications/", mapping.resolveLocalFromRemote(URI.create("http://portals.apache.org/applications/")));
+        assertEquals("/portals/applications/webcontent2/index.html", mapping.resolveLocalFromRemote(URI.create("http://portals.apache.org/applications/webcontent2/index.html")));
+    }
+}

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/WEB-INF/rproxy-mappings.yaml
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/WEB-INF/rproxy-mappings.yaml?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/WEB-INF/rproxy-mappings.yaml (original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/WEB-INF/rproxy-mappings.yaml Sat Jan  3 20:05:55 2015
@@ -21,18 +21,32 @@ contentRewriters:
 
 --- !simple
 local: /portals/bridges/
-remote: http://portals.apache.org/bridges/
+remote: //portals.apache.org/bridges/
+contentRewriters:
+    text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter []
+
+--- !simple
+local: /localhost/examples1/
+remote: //localhost:8080/webcontent2/examples1/
 contentRewriters:
     text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter []
 
 --- !regex
 localPattern: ^/apache/(\w+)/(.*)$
-remoteReplace: http://$1.apache.org/$2
-remotePattern: ^http://(\w+)\.apache\.org/(.*)$
+remoteReplace: //$1.apache.org/$2
+remotePattern: ^https?://(\w+)\.apache\.org/(.*)$
 localReplace: /apache/$1/$2
 contentRewriters:
     text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter []
 
+--- !regex
+localPattern: ^/localhost/examples2/(.*)$
+remoteReplace: //localhost:8080/webcontent2/examples2/$1
+remotePattern: ^https?://localhost:8080/webcontent2/examples2/(.*)$
+localReplace: /localhost/examples2/$1
+contentRewriters:
+    text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter []
+
 --- !simple
 local: /
 remote: http://apache.org/

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/WEB-INF/web.xml?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/WEB-INF/web.xml (original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/WEB-INF/web.xml Sat Jan  3 20:05:55 2015
@@ -56,6 +56,10 @@
         /WEB-INF/rproxy-mappings.yaml
       </param-value>
     </init-param>
+    <init-param>
+      <param-name>ssl-hostname-verifier</param-name>
+      <param-value>ALLOW_ALL_HOSTNAME_VERIFIER</param-value>
+    </init-param>
   </servlet>
 
   <!-- Map /rproxyservlet/* path to the Reverse Proxy Servlet -->

Added: portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples1/mission.html
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples1/mission.html?rev=1649240&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples1/mission.html (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples1/mission.html Sat Jan  3 20:05:55 2015
@@ -0,0 +1,205 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!-- 
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+<html>
+<head>
+<title>The Apache Portals Site - Apache Portals Mission</title>
+<style type="text/css" media="all">
+@import url("http://portals.apache.org/style/maven-base.css");
+
+@import url("http://portals.apache.org/style/maven-theme.css");
+</style>
+<link rel="stylesheet" href="http://portals.apache.org/style/print.css"
+	type="text/css" media="print"></link>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"></meta>
+<meta name="author" content="David Sean Taylor"></meta>
+<meta name="email" content="taylor@apache.org"></meta>
+</head>
+<body class="composite">
+	<div id="banner">
+		<a href="http://www.apache.org/" id="organizationLogo"><img
+			alt="Apache Software Foundation"
+			src="http://portals.apache.org/images/apache.gif"></img></a><a
+			href="http://portals.apache.org/" id="projectLogo"><img
+			alt="Apache Portals"
+			src="http://portals.apache.org/images/apache-portals.gif"></img></a>
+		<div class="clear">
+			<hr></hr>
+		</div>
+	</div>
+	<div id="breadcrumbs">
+		<div class="xleft">Last published: 20 April 2010</div>
+		<div class="xright">
+
+			<a href="http://portals.apache.org/jetspeed-2/">Jetspeed-2</a> <span
+				class="separator">|</span> <a
+				href="http://portals.apache.org/bridges/">Bridges</a> <span
+				class="separator">|</span> <a
+				href="http://portals.apache.org/pluto/">Pluto</a> <span
+				class="separator">|</span> <a
+				href="http://portals.apache.org/applications/">Applications</a> <span
+				class="separator">|</span> <a
+				href="http://portals.apache.org/jetspeed-1/">Jetspeed-1</a>
+		</div>
+		<div class="clear">
+			<hr></hr>
+		</div>
+	</div>
+	<div id="leftColumn">
+		<div id="navcolumn">
+			<div id="menuAbout_Apache_Portals">
+				<h5>About Apache Portals</h5>
+				<ul>
+					<li class="none"><a
+						href="http://portals.apache.org/index.html">Overview</a></li>
+					<li class="none"><strong><a
+							href="http://portals.apache.org/mission.html">Our Mission</a></strong></li>
+					<li class="none"><a href="http://portals.apache.org/news.html">News
+							and Status</a></li>
+					<li class="none"><a
+						href="http://www.apache.org/foundation/how-it-works.html"
+						class="externalLink" title="External Link">How the ASF Works</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/guidelines.html">Project
+							Guidelines</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/whoweare.html">Who We Are</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/supporting.html">Supporting
+							Organizations</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/license.html">License</a></li>
+				</ul>
+			</div>
+			<div id="menuResources">
+				<h5>Resources</h5>
+				<ul>
+					<li class="none"><a
+						href="http://portals.apache.org/download.html">Downloads</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/mail-lists.html">Mailing Lists</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/issue-tracking.html">Issue
+							Tracking</a></li>
+					<li class="none"><a href="http://portals.apache.org/wiki.html">Wikis</a></li>
+				</ul>
+			</div>
+			<div id="menuPortals_Sub_projects">
+				<h5>Portals Sub projects</h5>
+				<ul>
+					<li class="none"><a
+						href="http://portals.apache.org/jetspeed-2/">Jetspeed-2</a></li>
+					<li class="none"><a href="http://portals.apache.org/pluto/">Pluto</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/applications/">Applications</a></li>
+					<li class="none"><a href="http://portals.apache.org/bridges/">Bridges</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/jetspeed-1/">Jetspeed-1</a></li>
+				</ul>
+			</div>
+			<div id="menuDevelopment">
+				<h5>Development</h5>
+				<ul>
+					<li class="none"><a href="http://www.apache.org/dev/"
+						class="externalLink" title="External Link">Developer Resources</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/development/code-standards.html">Coding
+							Standards</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/development/documentation.html">Documentation
+							Standards</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/development/developer-links.html">Developer
+							Resources</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/development/further-reading.html">Further
+							Reading</a></li>
+				</ul>
+			</div>
+		</div>
+	</div>
+	<div id="bodyColumn">
+		<div class="contentBox">
+            <div class="section">
+                <a name="Test_Cases"></a>
+                <h2>Test Cases</h2>
+                <p>
+                  <a href="redirection.jsp">Test Redirection</a>
+                </p>
+            </div>
+			<div class="section">
+				<a name="Mission"></a>
+				<h2>Mission</h2>
+				<p>
+					<b>Apache Portals</b> exists to promote the use of open source
+					portal technology. We view portals as an important technology in in
+					the growing portal and web application environments. We intend to
+					build freely available portal software in order to promote the use
+					of this technology.
+				</p>
+				<p>
+					To provide reference implementations Java and W3C Standards such as
+					the
+					<ul>
+						<li>Java Portlet Standard (Pluto)</li>
+						<li>WSRP Portlet Standard (WSRP-4J)</li>
+					</ul>
+					To provide portal implementations including:
+					<ul>
+						<li>Cocoon Portal</li>
+						<li>Jetspeed-1</li>
+						<li>Jetspeed-2</li>
+						<li>PHP Portals (TBD)</li>
+					</ul>
+					To provide fully working and standardized portlet applications:
+					<ul>
+						<li>Jetspeed Content Replication Engine</li>
+						<li>Jetspeed Portal Administration Application</li>
+						<li>(TBD)</li>
+					</ul>
+					To provide common frameworks and tools for developing portal
+					software
+					<ul>
+						<li>CPS (Cornerstone Portlet Services)</li>
+						<li>Struts Portlet Application Framework</li>
+						<li>Python Portlet Application Framework</li>
+						<li>Turbine Portlet Application Framework</li>
+					</ul>
+					To provide portal interoperability frameworks and tools for
+					programming languages including
+					<ul>
+						<li>Java</li>
+						<li>Perl</li>
+						<li>PHP</li>
+						<li>Python</li>
+						<li>...</li>
+					</ul>
+				</p>
+			</div>
+		</div>
+	</div>
+	<div class="clear">
+		<hr></hr>
+	</div>
+	<div id="footer">
+		<div class="xright">� 2004-2010, Apache Software Foundation</div>
+		<div class="clear">
+			<hr></hr>
+		</div>
+	</div>
+</body>
+</html>
\ No newline at end of file

Added: portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples1/redirection.jsp
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples1/redirection.jsp?rev=1649240&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples1/redirection.jsp (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples1/redirection.jsp Sat Jan  3 20:05:55 2015
@@ -0,0 +1,5 @@
+<%@ page language="java" %>
+<%
+response.sendRedirect("mission.html");
+return;
+%>
\ No newline at end of file

Added: portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples2/mission.html
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples2/mission.html?rev=1649240&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples2/mission.html (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples2/mission.html Sat Jan  3 20:05:55 2015
@@ -0,0 +1,205 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!-- 
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+<html>
+<head>
+<title>The Apache Portals Site - Apache Portals Mission</title>
+<style type="text/css" media="all">
+@import url("http://portals.apache.org/style/maven-base.css");
+
+@import url("http://portals.apache.org/style/maven-theme.css");
+</style>
+<link rel="stylesheet" href="http://portals.apache.org/style/print.css"
+	type="text/css" media="print"></link>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"></meta>
+<meta name="author" content="David Sean Taylor"></meta>
+<meta name="email" content="taylor@apache.org"></meta>
+</head>
+<body class="composite">
+	<div id="banner">
+		<a href="http://www.apache.org/" id="organizationLogo"><img
+			alt="Apache Software Foundation"
+			src="http://portals.apache.org/images/apache.gif"></img></a><a
+			href="http://portals.apache.org/" id="projectLogo"><img
+			alt="Apache Portals"
+			src="http://portals.apache.org/images/apache-portals.gif"></img></a>
+		<div class="clear">
+			<hr></hr>
+		</div>
+	</div>
+	<div id="breadcrumbs">
+		<div class="xleft">Last published: 20 April 2010</div>
+		<div class="xright">
+
+			<a href="http://portals.apache.org/jetspeed-2/">Jetspeed-2</a> <span
+				class="separator">|</span> <a
+				href="http://portals.apache.org/bridges/">Bridges</a> <span
+				class="separator">|</span> <a
+				href="http://portals.apache.org/pluto/">Pluto</a> <span
+				class="separator">|</span> <a
+				href="http://portals.apache.org/applications/">Applications</a> <span
+				class="separator">|</span> <a
+				href="http://portals.apache.org/jetspeed-1/">Jetspeed-1</a>
+		</div>
+		<div class="clear">
+			<hr></hr>
+		</div>
+	</div>
+	<div id="leftColumn">
+		<div id="navcolumn">
+			<div id="menuAbout_Apache_Portals">
+				<h5>About Apache Portals</h5>
+				<ul>
+					<li class="none"><a
+						href="http://portals.apache.org/index.html">Overview</a></li>
+					<li class="none"><strong><a
+							href="http://portals.apache.org/mission.html">Our Mission</a></strong></li>
+					<li class="none"><a href="http://portals.apache.org/news.html">News
+							and Status</a></li>
+					<li class="none"><a
+						href="http://www.apache.org/foundation/how-it-works.html"
+						class="externalLink" title="External Link">How the ASF Works</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/guidelines.html">Project
+							Guidelines</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/whoweare.html">Who We Are</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/supporting.html">Supporting
+							Organizations</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/license.html">License</a></li>
+				</ul>
+			</div>
+			<div id="menuResources">
+				<h5>Resources</h5>
+				<ul>
+					<li class="none"><a
+						href="http://portals.apache.org/download.html">Downloads</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/mail-lists.html">Mailing Lists</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/issue-tracking.html">Issue
+							Tracking</a></li>
+					<li class="none"><a href="http://portals.apache.org/wiki.html">Wikis</a></li>
+				</ul>
+			</div>
+			<div id="menuPortals_Sub_projects">
+				<h5>Portals Sub projects</h5>
+				<ul>
+					<li class="none"><a
+						href="http://portals.apache.org/jetspeed-2/">Jetspeed-2</a></li>
+					<li class="none"><a href="http://portals.apache.org/pluto/">Pluto</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/applications/">Applications</a></li>
+					<li class="none"><a href="http://portals.apache.org/bridges/">Bridges</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/jetspeed-1/">Jetspeed-1</a></li>
+				</ul>
+			</div>
+			<div id="menuDevelopment">
+				<h5>Development</h5>
+				<ul>
+					<li class="none"><a href="http://www.apache.org/dev/"
+						class="externalLink" title="External Link">Developer Resources</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/development/code-standards.html">Coding
+							Standards</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/development/documentation.html">Documentation
+							Standards</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/development/developer-links.html">Developer
+							Resources</a></li>
+					<li class="none"><a
+						href="http://portals.apache.org/development/further-reading.html">Further
+							Reading</a></li>
+				</ul>
+			</div>
+		</div>
+	</div>
+	<div id="bodyColumn">
+		<div class="contentBox">
+            <div class="section">
+                <a name="Test_Cases"></a>
+                <h2>Test Cases</h2>
+                <p>
+                  <a href="redirection.jsp">Test Redirection</a>
+                </p>
+            </div>
+			<div class="section">
+				<a name="Mission"></a>
+				<h2>Mission</h2>
+				<p>
+					<b>Apache Portals</b> exists to promote the use of open source
+					portal technology. We view portals as an important technology in in
+					the growing portal and web application environments. We intend to
+					build freely available portal software in order to promote the use
+					of this technology.
+				</p>
+				<p>
+					To provide reference implementations Java and W3C Standards such as
+					the
+					<ul>
+						<li>Java Portlet Standard (Pluto)</li>
+						<li>WSRP Portlet Standard (WSRP-4J)</li>
+					</ul>
+					To provide portal implementations including:
+					<ul>
+						<li>Cocoon Portal</li>
+						<li>Jetspeed-1</li>
+						<li>Jetspeed-2</li>
+						<li>PHP Portals (TBD)</li>
+					</ul>
+					To provide fully working and standardized portlet applications:
+					<ul>
+						<li>Jetspeed Content Replication Engine</li>
+						<li>Jetspeed Portal Administration Application</li>
+						<li>(TBD)</li>
+					</ul>
+					To provide common frameworks and tools for developing portal
+					software
+					<ul>
+						<li>CPS (Cornerstone Portlet Services)</li>
+						<li>Struts Portlet Application Framework</li>
+						<li>Python Portlet Application Framework</li>
+						<li>Turbine Portlet Application Framework</li>
+					</ul>
+					To provide portal interoperability frameworks and tools for
+					programming languages including
+					<ul>
+						<li>Java</li>
+						<li>Perl</li>
+						<li>PHP</li>
+						<li>Python</li>
+						<li>...</li>
+					</ul>
+				</p>
+			</div>
+		</div>
+	</div>
+	<div class="clear">
+		<hr></hr>
+	</div>
+	<div id="footer">
+		<div class="xright">� 2004-2010, Apache Software Foundation</div>
+		<div class="clear">
+			<hr></hr>
+		</div>
+	</div>
+</body>
+</html>
\ No newline at end of file

Added: portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples2/redirection.jsp
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples2/redirection.jsp?rev=1649240&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples2/redirection.jsp (added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/examples2/redirection.jsp Sat Jan  3 20:05:55 2015
@@ -0,0 +1,5 @@
+<%@ page language="java" %>
+<%
+response.sendRedirect("mission.html");
+return;
+%>
\ No newline at end of file

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/index.jsp
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/index.jsp?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/index.jsp (original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/test/webapp/index.jsp Sat Jan  3 20:05:55 2015
@@ -31,6 +31,8 @@ limitations under the License.
   <li><a href="/webcontent2/rproxyservlet/portals/bridges/" target="_blank">Apache Portals Bridges (reverse proxied)</a></li>
   <li><a href="/webcontent2/rproxyservlet/apache/portals/" target="_blank">Apache Portals (reverse proxied)</a></li>
   <li><a href="/webcontent2/rproxyservlet/" target="_blank">Apache Software Foundation (reverse proxied)</a></li>
+  <li><a href="/webcontent2/rproxyservlet/localhost/examples1/mission.html" target="_blank">Local Mission 1 (reverse proxied)</a></li>
+  <li><a href="/webcontent2/rproxyservlet/localhost/examples2/mission.html" target="_blank">Local Mission 2 (reverse proxied)</a></li>
   <li><a href="portals-includes-servlet.jsp" target="_blank">JSP Include for Apache Portals Applications (reverse proxied)</a></li>
 </ul>
 
@@ -42,6 +44,8 @@ limitations under the License.
   <li><a href="/webcontent2/rproxyfilter/portals/bridges/" target="_blank">Apache Portals Bridges (reverse proxied)</a></li>
   <li><a href="/webcontent2/rproxyfilter/apache/portals/" target="_blank">Apache Portals (reverse proxied)</a></li>
   <li><a href="/webcontent2/rproxyfilter/" target="_blank">Apache Software Foundation (reverse proxied)</a></li>
+  <li><a href="/webcontent2/rproxyfilter/localhost/examples1/mission.html" target="_blank">Local Mission 1 (reverse proxied)</a></li>
+  <li><a href="/webcontent2/rproxyfilter/localhost/examples2/mission.html" target="_blank">Local Mission 2 (reverse proxied)</a></li>
   <li><a href="portals-includes-filter.jsp" target="_blank">JSP Include for Apache Portals Applications (reverse proxied)</a></li>
 </ul>
 

Modified: portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/portlet.xml
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/portlet.xml?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/portlet.xml (original)
+++ portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/portlet.xml Sat Jan  3 20:05:55 2015
@@ -152,12 +152,12 @@
       <preference>
         <name>SRC</name>
         <!-- <value>http://portals.apache.org/</value> -->
-        <value>http://localhost:${serverPort}/webcontent2/examples/mission.html</value>
+        <value>//localhost:${serverPort}/webcontent2/examples/mission.html</value>
       </preference>
       <preference>
         <name>PROXYREMOTEURL</name>
         <!-- <value>http://portals.apache.org/</value> -->
-        <value>http://localhost:${serverPort}/webcontent2/examples/</value>
+        <value>//localhost:${serverPort}/webcontent2/examples/</value>
       </preference>
       <preference>
         <name>PROXYLOCALPATH</name>

Modified: portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/rproxy-mappings.yaml
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/rproxy-mappings.yaml?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/rproxy-mappings.yaml (original)
+++ portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/rproxy-mappings.yaml Sat Jan  3 20:05:55 2015
@@ -15,8 +15,8 @@
 
 --- !regex
 localPattern: ^/localhost_(\d+)/(.*)$
-remoteReplace: http://localhost:$1/$2
-remotePattern: ^http://localhost:(\d+)/(.*)$
+remoteReplace: //localhost:$1/$2
+remotePattern: ^https?://localhost:(\d+)/(.*)$
 localReplace: /localhost_$1/$2
 contentRewriters:
     text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter []

Modified: portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/web.xml?rev=1649240&r1=1649239&r2=1649240&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/web.xml (original)
+++ portals/applications/webcontent/trunk/war/src/main/webapp/WEB-INF/web.xml Sat Jan  3 20:05:55 2015
@@ -57,6 +57,10 @@
         /WEB-INF/rproxy-mappings.yaml
       </param-value>
     </init-param>
+    <init-param>
+      <param-name>ssl-hostname-verifier</param-name>
+      <param-value>ALLOW_ALL_HOSTNAME_VERIFIER</param-value>
+    </init-param>
   </servlet>
 
   <!-- Map *.vm files to Velocity  -->