Author: ivaynberg
Date: Tue Dec  6 01:06:38 2011
New Revision: 1210730

URL: http://svn.apache.org/viewvc?rev=1210730&view=rev
Log:
made https mapper more customizable, and the code simpler and easier to follow

Added:
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/Scheme.java
    
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/https/HttpsMapperTest.java
Removed:
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsRequestChecker.java
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/Protocol.java
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/SwitchProtocolRequestHandler.java
    
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/https/HttpsRequestCheckerTest.java
    
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/https/SwitchProtocolRequestHandlerTest.java
Modified:
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsConfig.java
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsMapper.java
    
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/https/HttpsMapperApplicationTest.java

Modified: 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsConfig.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsConfig.java?rev=1210730&r1=1210729&r2=1210730&view=diff
==============================================================================
--- 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsConfig.java
 (original)
+++ 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsConfig.java
 Tue Dec  6 01:06:38 2011
@@ -101,8 +101,8 @@ public class HttpsConfig
        }
 
        /**
-        * Sets whether or not a new session is created before redirecting from 
{@code http} to {@code
-        * https}
+        * Sets whether or not a new session is created before redirecting from 
{@code http} to
+        * {@code https}
         * <p>
         * BE VERY CAREFUL WHEN SETTING THIS VALUE TO {@code false}.
         * 

Modified: 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsMapper.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsMapper.java?rev=1210730&r1=1210729&r2=1210730&view=diff
==============================================================================
--- 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsMapper.java
 (original)
+++ 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsMapper.java
 Tue Dec  6 01:06:38 2011
@@ -1,27 +1,19 @@
-/*
- * 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.wicket.protocol.https;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.apache.wicket.Session;
+import org.apache.wicket.request.IRequestCycle;
 import org.apache.wicket.request.IRequestHandler;
 import org.apache.wicket.request.IRequestMapper;
 import org.apache.wicket.request.Request;
 import org.apache.wicket.request.Url;
-import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.request.component.IRequestablePage;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.handler.IPageClassRequestHandler;
+import org.apache.wicket.request.http.WebRequest;
+import org.apache.wicket.request.http.WebResponse;
+import org.apache.wicket.util.collections.ClassMetaCache;
 
 /**
  * A {@link IRequestMapper} that will issue a redirect to secured 
communication (over https) if the
@@ -49,94 +41,290 @@ import org.apache.wicket.util.lang.Args;
  * 
  * any request to <em>http://hostname:httpPort/secured</em> will be redirected 
to
  * <em>https://hostname:httpsPort/secured</em>
+ * 
+ * @author igor
  */
 public class HttpsMapper implements IRequestMapper
 {
+       private final HttpsConfig config;
+       private final IRequestMapper delegate;
+       private final ClassMetaCache<Scheme> cache = new 
ClassMetaCache<Scheme>();
+
        /**
-        * The original request mapper that will actually resolve the page
+        * Constructor
+        * 
+        * @param delegate
+        * @param config
         */
-       private final IRequestMapper delegate;
+       public HttpsMapper(IRequestMapper delegate, HttpsConfig config)
+       {
+               this.delegate = delegate;
+               this.config = config;
+       }
+
+       @Override
+       public final int getCompatibilityScore(Request request)
+       {
+               return delegate.getCompatibilityScore(request);
+       }
+
+
+       @Override
+       public final IRequestHandler mapRequest(Request request)
+       {
+               IRequestHandler handler = delegate.mapRequest(request);
+
+               Scheme desired = getDesiredSchemeFor(handler);
+               Scheme current = getSchemeOf(request);
+               if (!desired.isCompatibleWith(current))
+               {
+                       // we are currently on the wrong scheme for this handler
+
+                       // construct a url for the handler on the correct scheme
+                       String url = createRedirectUrl(handler, request, 
desired);
+
+                       // replace handler with one that will redirect to the 
created url
+                       handler = createRedirectHandler(url);
+               }
+               return handler;
+       }
+
+       @Override
+       public final Url mapHandler(IRequestHandler handler)
+       {
+               return mapHandler(handler, RequestCycle.get().getRequest());
+       }
 
        /**
-        * The object that brings the settings for communication over https
+        * Creates the {@link IRequestHandler} that will be responsible for the 
redirect
+        * 
+        * @param url
+        * @return request handler
         */
-       private final HttpsConfig httpsConfig;
+       protected IRequestHandler createRedirectHandler(String url)
+       {
+               return new RedirectHandler(url, config);
+       }
 
        /**
-        * A helper that will check the resolved page for @{@link RequireHttps} 
annotation
+        * Construts a redirect url that should switch the user to the 
specified {@code scheme}
+        * 
+        * @param handler
+        *            request handler being accessed
+        * @param request
+        *            current request
+        * @param scheme
+        *            desired scheme for the redirect url
+        * @return url
         */
-       private final HttpsRequestChecker checker;
+       protected String createRedirectUrl(IRequestHandler handler, Request 
request, Scheme scheme)
+       {
+               HttpServletRequest req = 
(HttpServletRequest)((WebRequest)request).getContainerRequest();
+               String url = scheme.urlName() + "://";
+               url += req.getServerName();
+               if (!scheme.usesStandardPort(config))
+               {
+                       url += ":" + scheme.getPort(config);
+               }
+               url += req.getRequestURI();
+               if (req.getQueryString() != null)
+               {
+                       url += "?" + req.getQueryString();
+               }
+               return url;
+       }
+
 
        /**
-        * Construct.
+        * Creates a url for the handler. Modifies it with the correct {@link 
Scheme} if necessary.
         * 
-        * @param delegate
-        * @param httpsConfig
+        * @param handler
+        * @param request
+        * @return url
         */
-       public HttpsMapper(final IRequestMapper delegate, final HttpsConfig 
httpsConfig)
+       final Url mapHandler(IRequestHandler handler, Request request)
        {
-               Args.notNull(delegate, "delegate");
-               Args.notNull(httpsConfig, "httpsConfig");
+               Url url = delegate.mapHandler(handler);
 
-               this.delegate = delegate;
-               this.httpsConfig = httpsConfig;
-               checker = new HttpsRequestChecker();
+               Scheme desired = getDesiredSchemeFor(handler);
+               Scheme current = getSchemeOf(request);
+               if (!desired.isCompatibleWith(current))
+               {
+                       // the generated url does not have the correct scheme, 
set it (which in turn will cause
+                       // the url to be rendered in its full representation)
+                       url.setProtocol(desired.urlName());
+                       if (url.getPort() != null || 
!desired.usesStandardPort(config))
+                       {
+                               url.setPort(desired.getPort(config));
+                       }
+               }
+               return url;
        }
 
+
        /**
-        * {@inheritDoc}
+        * Figures out which {@link Scheme} should be used to access the 
request handler
+        * 
+        * @param handler
+        *            request handler
+        * @return {@link Scheme}
         */
-       @Override
-       public IRequestHandler mapRequest(final Request request)
+       protected Scheme getDesiredSchemeFor(IRequestHandler handler)
+       {
+               if (handler instanceof IPageClassRequestHandler)
+               {
+                       return 
getDesiredSchemeFor(((IPageClassRequestHandler)handler).getPageClass());
+               }
+               return Scheme.ANY;
+       }
+
+       /**
+        * Determines the {@link Scheme} of the request
+        * 
+        * @param url
+        * @param request
+        * @throws IlelgalStateException
+        *             if protocol cannot be determined
+        * @return {@link Scheme#HTTPS} or {@link Scheme#HTTP}
+        */
+       protected Scheme getSchemeOf(Request request)
        {
-               IRequestHandler requestHandler = delegate.mapRequest(request);
+               HttpServletRequest req = 
(HttpServletRequest)((WebRequest)request).getContainerRequest();
 
-               if (requestHandler != null)
+               if ("https".equalsIgnoreCase(req.getScheme()))
                {
-                       final IRequestHandler httpsHandler = 
checker.checkSecureIncoming(requestHandler,
-                               httpsConfig);
+                       return Scheme.HTTPS;
+               }
+               else if ("http".equalsIgnoreCase(req.getScheme()))
+               {
+                       return Scheme.HTTP;
+               }
+               else
+               {
+                       throw new IllegalStateException("Could not resolve 
protocol for request: " + req);
+               }
+       }
 
-                       // XXX do we need to check if httpsHandler is instance 
of SwitchProtocolRequestHandler
-                       if (httpsConfig.isPreferStateful())
+       /**
+        * Determines which {@link Scheme} should be used to access the page
+        * 
+        * @param pageClass
+        *            type of page
+        * @return {@link Scheme}
+        */
+       protected Scheme getDesiredSchemeFor(Class<? extends IRequestablePage> 
pageClass)
+       {
+               Scheme SCHEME = cache.get(pageClass);
+               if (SCHEME == null)
+               {
+                       if (hasSecureAnnotation(pageClass))
                        {
-                               // we need to persist the session before a 
redirect to https so the session lasts
-                               // across both http and https calls.
-                               Session.get().bind();
+                               SCHEME = Scheme.HTTPS;
                        }
-
-                       requestHandler = httpsHandler;
+                       else
+                       {
+                               SCHEME = Scheme.HTTP;
+                       }
+                       cache.put(pageClass, SCHEME);
                }
+               return SCHEME;
+       }
 
-               return requestHandler;
+       /**
+        * @return config with which this mapper was created
+        */
+       public final HttpsConfig getConfig()
+       {
+               return config;
        }
 
        /**
-        * {@inheritDoc}
+        * Checks if the specified {@code type} has the {@link RequireHttps} 
annotation
+        * 
+        * @param type
+        * @return {@code true} iff {@code type} has the {@link RequireHttps} 
annotation
         */
-       @Override
-       public int getCompatibilityScore(final Request request)
+       private boolean hasSecureAnnotation(Class<?> type)
        {
-               return delegate.getCompatibilityScore(request);
+               if (type.getAnnotation(RequireHttps.class) != null)
+               {
+                       return true;
+               }
+
+               for (Class<?> iface : type.getInterfaces())
+               {
+                       if (hasSecureAnnotation(iface))
+                       {
+                               return true;
+                       }
+               }
+
+               if (type.getSuperclass() != null)
+               {
+                       return hasSecureAnnotation(type.getSuperclass());
+               }
+               return false;
        }
 
+
        /**
-        * {@inheritDoc}
+        * Handler that takes care of redirecting
+        * 
+        * @author igor
         */
-       @Override
-       public Url mapHandler(IRequestHandler requestHandler)
+       public static class RedirectHandler implements IRequestHandler
        {
-               Url url = delegate.mapHandler(requestHandler);
-               switch (checker.getProtocol(requestHandler))
+               private final String url;
+               private final HttpsConfig config;
+
+               /**
+                * Constructor
+                * 
+                * @param config
+                *            https config
+                * @param url
+                *            redirect location
+                */
+               public RedirectHandler(String url, HttpsConfig config)
                {
-                       case HTTP :
-                               url.setProtocol("http");
-                               url.setPort(httpsConfig.getHttpPort());
-                               break;
-                       case HTTPS :
-                               url.setProtocol("https");
-                               url.setPort(httpsConfig.getHttpsPort());
-                               break;
+                       this.url = url;
+                       this.config = config;
                }
-               return url;
+
+               /**
+                * @return redirect location
+                */
+               public String getUrl()
+               {
+                       return url;
+               }
+
+               @Override
+               public void respond(IRequestCycle requestCycle)
+               {
+                       String location = url.toString();
+
+                       if (location.startsWith("/"))
+                       {
+                               // context-absolute url
+                               location = 
requestCycle.getUrlRenderer().renderContextRelativeUrl(location);
+                       }
+
+                       if (config.isPreferStateful())
+                       {
+                               // we need to persist the session before a 
redirect to https so the session lasts
+                               // across both http and https calls.
+                               Session.get().bind();
+                       }
+
+                       WebResponse response = 
(WebResponse)requestCycle.getResponse();
+                       response.sendRedirect(location);
+               }
+
+               @Override
+               public void detach(IRequestCycle requestCycle)
+               {
+               }
+
        }
 }

Added: 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/Scheme.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/Scheme.java?rev=1210730&view=auto
==============================================================================
--- 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/Scheme.java
 (added)
+++ 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/https/Scheme.java
 Tue Dec  6 01:06:38 2011
@@ -0,0 +1,88 @@
+package org.apache.wicket.protocol.https;
+
+/**
+ * Url scheme
+ * 
+ * @author igor
+ */
+enum Scheme {
+       /** https */
+       HTTPS {
+               @Override
+               public boolean usesStandardPort(HttpsConfig config)
+               {
+                       return getPort(config) == 443;
+               }
+
+               @Override
+               public int getPort(HttpsConfig config)
+               {
+                       return config.getHttpsPort();
+               }
+       },
+       /** http */
+       HTTP {
+               @Override
+               public boolean usesStandardPort(HttpsConfig config)
+               {
+                       return getPort(config) == 80;
+               }
+
+               @Override
+               public int getPort(HttpsConfig config)
+               {
+                       return config.getHttpPort();
+               }
+       },
+       /** any, aka preserve current */
+       ANY {
+               @Override
+               public String urlName()
+               {
+                       throw new UnsupportedOperationException();
+               }
+
+               @Override
+               public boolean isCompatibleWith(Scheme other)
+               {
+                       return true;
+               }
+
+               @Override
+               public boolean usesStandardPort(HttpsConfig config)
+               {
+                       throw new UnsupportedOperationException();
+               }
+
+               @Override
+               public int getPort(HttpsConfig config)
+               {
+                       throw new UnsupportedOperationException();
+               }
+       };
+
+
+       /**
+        * @return scheme's url name
+        */
+       public String urlName()
+       {
+               return name().toLowerCase();
+       }
+
+       /**
+        * Checks if two schemes are compatible. Compatible schemes do not 
require a redirect from the
+        * current scheme to the {@code other}.
+        * 
+        * @param other
+        * @return {@code true} iff the schemes are compatible.
+        */
+       public boolean isCompatibleWith(Scheme other)
+       {
+               return this == other;
+       }
+
+       public abstract boolean usesStandardPort(HttpsConfig config);
+
+       public abstract int getPort(HttpsConfig config);
+}

Modified: 
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/https/HttpsMapperApplicationTest.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/https/HttpsMapperApplicationTest.java?rev=1210730&r1=1210729&r2=1210730&view=diff
==============================================================================
--- 
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/https/HttpsMapperApplicationTest.java
 (original)
+++ 
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/https/HttpsMapperApplicationTest.java
 Tue Dec  6 01:06:38 2011
@@ -28,7 +28,7 @@ import org.junit.Test;
  */
 public class HttpsMapperApplicationTest
 {
-       @SuppressWarnings({"unchecked"})
+       @SuppressWarnings({ "unchecked" })
        private <T extends Page> T requestPage(WicketTester tester, Class<T> 
pageClass)
        {
                Page page = tester.startPage(pageClass);
@@ -43,11 +43,10 @@ public class HttpsMapperApplicationTest
        public void switchDefaultToHttpsWithDefaultPorts()
        {
                WicketTester tester = new WicketTester(new 
HttpsMapperApplication());
-               
+
                requestPage(tester, HttpsPage.class);
-               
+
                assertEquals("https", tester.getLastRequest().getScheme());
-               assertEquals(443, tester.getLastRequest().getServerPort());
        }
 
        @Test
@@ -68,11 +67,10 @@ public class HttpsMapperApplicationTest
 
                tester.getRequest().setScheme("https");
                tester.getRequest().setServerPort(443);
-               
+
                requestPage(tester, HttpPage.class);
-               
+
                assertEquals("http", tester.getLastRequest().getScheme());
-               assertEquals(80, tester.getLastRequest().getServerPort());
        }
 
        @Test
@@ -126,7 +124,7 @@ public class HttpsMapperApplicationTest
 
                assertEquals("https", tester.getLastRequest().getScheme());
                assertEquals(443, tester.getLastRequest().getServerPort());
-               
+
                assertEquals("https", tester.getRequest().getScheme());
                assertEquals(443, tester.getRequest().getServerPort());
        }

Added: 
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/https/HttpsMapperTest.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/https/HttpsMapperTest.java?rev=1210730&view=auto
==============================================================================
--- 
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/https/HttpsMapperTest.java
 (added)
+++ 
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/https/HttpsMapperTest.java
 Tue Dec  6 01:06:38 2011
@@ -0,0 +1,219 @@
+package org.apache.wicket.protocol.https;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+import static org.hamcrest.Matchers.sameInstance;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.wicket.Page;
+import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
+import org.apache.wicket.protocol.https.HttpsMapper.RedirectHandler;
+import org.apache.wicket.request.IRequestHandler;
+import org.apache.wicket.request.IRequestMapper;
+import org.apache.wicket.request.Url;
+import org.apache.wicket.request.handler.PageProvider;
+import org.apache.wicket.request.handler.RenderPageRequestHandler;
+import org.junit.Test;
+
+public class HttpsMapperTest
+{
+       @Test
+       public void getDesiredSchemeOfPageClass()
+       {
+               IRequestMapper delegate = mock(IRequestMapper.class);
+               HttpsMapper mapper = new HttpsMapper(delegate, new 
HttpsConfig());
+
+               assertThat(mapper.getDesiredSchemeFor(SecurePage.class), 
is(Scheme.HTTPS));
+               
assertThat(mapper.getDesiredSchemeFor(SecureDecendantPage.class), 
is(Scheme.HTTPS));
+               assertThat(mapper.getDesiredSchemeFor(SecureMixinPage.class), 
is(Scheme.HTTPS));
+               assertThat(mapper.getDesiredSchemeFor(InsecurePage.class), 
is(Scheme.HTTP));
+       }
+
+       @Test
+       public void getDesiredSchemeOfHandler()
+       {
+               IRequestMapper delegate = mock(IRequestMapper.class);
+               HttpsMapper mapper = new HttpsMapper(delegate, new 
HttpsConfig());
+
+               IRequestHandler handler = new RenderPageRequestHandler(new 
PageProvider(SecurePage.class));
+               assertThat(mapper.getDesiredSchemeFor(handler), 
is(Scheme.HTTPS));
+
+               handler = new RenderPageRequestHandler(new 
PageProvider(InsecurePage.class));
+               assertThat(mapper.getDesiredSchemeFor(handler), 
is(Scheme.HTTP));
+
+               handler = mock(IRequestHandler.class);
+               assertThat(mapper.getDesiredSchemeFor(handler), is(Scheme.ANY));
+       }
+
+       @Test
+       public void getSchemeOfRequest()
+       {
+               IRequestMapper delegate = mock(IRequestMapper.class);
+               HttpsMapper mapper = new HttpsMapper(delegate, new 
HttpsConfig());
+
+               ServletWebRequest request = mock(ServletWebRequest.class);
+               HttpServletRequest req = mock(HttpServletRequest.class);
+               when(request.getContainerRequest()).thenReturn(req);
+
+               when(req.getScheme()).thenReturn("https");
+               assertThat(mapper.getSchemeOf(request), is(Scheme.HTTPS));
+
+               reset(req);
+               when(req.getScheme()).thenReturn("hTTps");
+               assertThat(mapper.getSchemeOf(request), is(Scheme.HTTPS));
+
+               reset(req);
+               when(req.getScheme()).thenReturn("http");
+               assertThat(mapper.getSchemeOf(request), is(Scheme.HTTP));
+
+               try
+               {
+                       reset(req);
+                       when(req.getScheme()).thenReturn("ftp");
+                       mapper.getSchemeOf(request);
+                       assertThat("expected error", false);
+               }
+               catch (IllegalStateException e)
+               { // expected
+
+               }
+       }
+
+       @Test
+       public void mapHandler()
+       {
+               IRequestMapper delegate = mock(IRequestMapper.class);
+               HttpsMapper mapper = new HttpsMapper(delegate, new 
HttpsConfig());
+
+               ServletWebRequest request = mock(ServletWebRequest.class);
+               HttpServletRequest req = mock(HttpServletRequest.class);
+               when(request.getContainerRequest()).thenReturn(req);
+
+               // rendering url to https page on http, set protocol
+               IRequestHandler handler = new RenderPageRequestHandler(new 
PageProvider(SecurePage.class));
+               Url url = new Url();
+               when(delegate.mapHandler(handler)).thenReturn(url);
+               when(req.getScheme()).thenReturn("http");
+               mapper.mapHandler(handler, request);
+               assertThat(url.getProtocol(), is("https"));
+
+               // render url to http page on http, ignore protocol
+               handler = new RenderPageRequestHandler(new 
PageProvider(InsecurePage.class));
+               url = new Url();
+               reset(delegate);
+               when(delegate.mapHandler(handler)).thenReturn(url);
+               when(req.getScheme()).thenReturn("http");
+               mapper.mapHandler(handler, request);
+               assertThat(url.getProtocol(), is(nullValue()));
+
+               // render url to http page on https, set protocol
+               handler = new RenderPageRequestHandler(new 
PageProvider(InsecurePage.class));
+               url = new Url();
+               reset(delegate);
+               when(delegate.mapHandler(handler)).thenReturn(url);
+               when(req.getScheme()).thenReturn("https");
+               mapper.mapHandler(handler, request);
+               assertThat(url.getProtocol(), is("http"));
+       }
+
+
+       @Test
+       public void mapRequest()
+       {
+               IRequestMapper delegate = mock(IRequestMapper.class);
+               HttpsMapper mapper = new HttpsMapper(delegate, new 
HttpsConfig());
+
+               ServletWebRequest request = mock(ServletWebRequest.class);
+               HttpServletRequest req = mock(HttpServletRequest.class);
+               when(request.getContainerRequest()).thenReturn(req);
+
+               // https handler on http request, redirect to https
+               setupRequest(req, "http", "localhost", 80, "/ctx", "foo=bar");
+               IRequestHandler handler = new RenderPageRequestHandler(new 
PageProvider(SecurePage.class));
+               when(delegate.mapRequest(request)).thenReturn(handler);
+               IRequestHandler resolved = mapper.mapRequest(request);
+               assertThat(resolved, is(instanceOf(RedirectHandler.class)));
+               assertThat(((RedirectHandler)resolved).getUrl(), 
is("https://localhost/ctx?foo=bar";));
+
+               // http handler on http request, return the original handler
+               handler = new RenderPageRequestHandler(new 
PageProvider(InsecurePage.class));
+               reset(delegate);
+               when(delegate.mapRequest(request)).thenReturn(handler);
+               setupRequest(req, "http", "localhost", 80, "/ctx", "foo=bar");
+               resolved = mapper.mapRequest(request);
+               assertThat(resolved, is(sameInstance(handler)));
+       }
+
+       @Test
+       public void mapRequestWithCustomPorts()
+       {
+               IRequestMapper delegate = mock(IRequestMapper.class);
+               HttpsMapper mapper = new HttpsMapper(delegate, new 
HttpsConfig(10, 20));
+
+               ServletWebRequest request = mock(ServletWebRequest.class);
+               HttpServletRequest req = mock(HttpServletRequest.class);
+               when(request.getContainerRequest()).thenReturn(req);
+
+               // https handler on http request, redirect to https
+               setupRequest(req, "http", "localhost", 10, "/ctx", "foo=bar");
+               IRequestHandler handler = new RenderPageRequestHandler(new 
PageProvider(SecurePage.class));
+               when(delegate.mapRequest(request)).thenReturn(handler);
+               IRequestHandler resolved = mapper.mapRequest(request);
+               assertThat(resolved, is(instanceOf(RedirectHandler.class)));
+               assertThat(((RedirectHandler)resolved).getUrl(), 
is("https://localhost:20/ctx?foo=bar";));
+
+               // http handler on http request, return the original handler
+               handler = new RenderPageRequestHandler(new 
PageProvider(InsecurePage.class));
+               reset(delegate);
+               when(delegate.mapRequest(request)).thenReturn(handler);
+               setupRequest(req, "https", "localhost", 20, "/ctx", "foo=bar");
+               resolved = mapper.mapRequest(request);
+               assertThat(resolved, is(instanceOf(RedirectHandler.class)));
+               assertThat(((RedirectHandler)resolved).getUrl(), 
is("http://localhost:10/ctx?foo=bar";));
+       }
+
+       private static void setupRequest(HttpServletRequest mock, String 
scheme, String host, int port,
+               String uri, String query)
+       {
+               reset(mock);
+               when(mock.getScheme()).thenReturn(scheme);
+               when(mock.getServerName()).thenReturn(host);
+               when(mock.getServerPort()).thenReturn(port);
+               when(mock.getRequestURI()).thenReturn(uri);
+               when(mock.getQueryString()).thenReturn(query);
+       }
+
+
+       @RequireHttps
+       private static class SecurePage extends Page
+       {
+
+       }
+
+       private static class InsecurePage extends Page
+       {
+
+       }
+
+       @RequireHttps
+       private static interface Secured
+       {
+
+       }
+
+       private static class SecureDecendantPage extends SecurePage
+       {
+
+       }
+
+       private static class SecureMixinPage extends Page implements Secured
+       {
+
+       }
+}
\ No newline at end of file


Reply via email to