/*
* 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 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.core.request.handler.PageProvider;
import org.apache.wicket.core.request.handler.RenderPageRequestHandler;
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.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"));
assertThat(url.getPort(), is(443));
// 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"));
assertThat(url.getPort(), is(80));
}
@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
{
}
}