You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ja...@apache.org on 2014/10/30 13:07:47 UTC
svn commit: r1635470 - in /felix/trunk/http/sslfilter: ./
src/main/java/org/apache/felix/http/sslfilter/internal/
src/test/java/org/apache/felix/http/sslfilter/internal/
Author: jawi
Date: Thu Oct 30 12:07:47 2014
New Revision: 1635470
URL: http://svn.apache.org/r1635470
Log:
FELIX-4420 - Implement sendRedirect:
- implemented original idea of overriding sendRedirect with logic for rewriting
relative and absolute URLs;
- added test case provided by [~chetanm] and extended it with some additional tests.
Added:
felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterJettyTest.java (with props)
Modified:
felix/trunk/http/sslfilter/pom.xml
felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java
felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java
Modified: felix/trunk/http/sslfilter/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/http/sslfilter/pom.xml?rev=1635470&r1=1635469&r2=1635470&view=diff
==============================================================================
--- felix/trunk/http/sslfilter/pom.xml (original)
+++ felix/trunk/http/sslfilter/pom.xml Thu Oct 30 12:07:47 2014
@@ -75,9 +75,9 @@
<dependencies>
<dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>servlet-api</artifactId>
- <version>2.3</version>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.http.servlet-api</artifactId>
+ <version>1.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -115,6 +115,13 @@
<version>3.2.1</version>
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ <version>${jetty.version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
Modified: felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java?rev=1635470&r1=1635469&r2=1635470&view=diff
==============================================================================
--- felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java (original)
+++ felix/trunk/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java Thu Oct 30 12:07:47 2014
@@ -26,6 +26,7 @@ import static org.apache.felix.http.sslf
import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTPS_PORT;
import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTP_PORT;
+import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
@@ -38,16 +39,19 @@ import javax.servlet.http.HttpServletRes
*/
class SslFilterResponse extends HttpServletResponseWrapper
{
+ private final URL requestURL;
private final String serverName;
private final String serverProto;
private final int serverPort;
private final String clientProto;
private final int clientPort;
- public SslFilterResponse(HttpServletResponse response, HttpServletRequest request)
+ public SslFilterResponse(HttpServletResponse response, HttpServletRequest request) throws MalformedURLException
{
super(response);
+ this.requestURL = new URL(request.getRequestURL().toString());
+
// Only rewrite URLs for the host & port the request was sent to...
this.serverName = request.getServerName();
this.serverPort = request.getServerPort();
@@ -102,6 +106,17 @@ class SslFilterResponse extends HttpServ
super.setHeader(name, value);
}
+ @Override
+ public void sendRedirect(String location) throws IOException
+ {
+ URL rewritten = rewriteUrlIfNeeded(location);
+ if (rewritten != null)
+ {
+ location = rewritten.toExternalForm();
+ }
+ super.sendRedirect(location);
+ }
+
private int normalizePort(String protocol, int port)
{
if (port > 0)
@@ -117,9 +132,22 @@ class SslFilterResponse extends HttpServ
private URL rewriteUrlIfNeeded(String value)
{
+ if (value == null)
+ {
+ return null;
+ }
+
try
{
- URL url = new URL(value);
+ URL url;
+ if (value.startsWith(this.serverProto.concat("://")))
+ {
+ url = new URL(value);
+ }
+ else
+ {
+ url = new URL(this.requestURL, value);
+ }
String actualProto = url.getProtocol();
Added: felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterJettyTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterJettyTest.java?rev=1635470&view=auto
==============================================================================
--- felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterJettyTest.java (added)
+++ felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterJettyTest.java Thu Oct 30 12:07:47 2014
@@ -0,0 +1,182 @@
+/*
+ * 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.felix.http.sslfilter.internal;
+
+import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HDR_LOCATION;
+import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HDR_X_FORWARDED_PROTO;
+import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HDR_X_FORWARDED_SSL;
+import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTP;
+import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTPS;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.EnumSet;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SslFilterJettyTest
+{
+ private InetSocketAddress serverAddress;
+
+ private Server server;
+ private ServletContextHandler context;
+ private boolean originalFollowRedirects;
+
+ @Before
+ public void setupServer() throws Exception
+ {
+ this.serverAddress = new InetSocketAddress("localhost", 8080);
+
+ this.context = new ServletContextHandler(ServletContextHandler.SESSIONS);
+ this.context.setContextPath("/");
+ this.context.addFilter(new FilterHolder(new SslFilter()), "/*", EnumSet.of(DispatcherType.REQUEST));
+
+ this.server = new Server(this.serverAddress);
+ this.server.setHandler(this.context);
+
+ this.originalFollowRedirects = HttpURLConnection.getFollowRedirects();
+ HttpURLConnection.setFollowRedirects(false);
+ }
+
+ @After
+ public void tearDown() throws Exception
+ {
+ HttpURLConnection.setFollowRedirects(this.originalFollowRedirects);
+
+ if (this.server != null)
+ {
+ this.server.stop();
+ }
+ }
+
+ @Test
+ public void testSslFilterWithRelativeRedirectURL() throws Exception
+ {
+ String servletPath = "/test";
+ String redirectPath = "/foo";
+
+ this.context.addServlet(new ServletHolder(new RedirectServlet(redirectPath)), servletPath);
+ this.server.start();
+
+ HttpURLConnection conn = openConnection(createURL(servletPath));
+
+ assertEquals(302, conn.getResponseCode());
+ String location = conn.getHeaderField(HDR_LOCATION);
+ assertTrue(location, location.startsWith(HTTPS));
+ }
+
+ @Test
+ public void testSslFilterWithAbsoluteRedirectURL() throws Exception
+ {
+ String servletPath = "/test";
+ String redirectPath = String.format("http://%s:%d/foo", this.serverAddress.getHostName(), this.serverAddress.getPort());
+
+ this.context.addServlet(new ServletHolder(new RedirectServlet(redirectPath)), servletPath);
+ this.server.start();
+
+ HttpURLConnection conn = openConnection(createURL(servletPath));
+
+ assertEquals(302, conn.getResponseCode());
+
+ String location = conn.getHeaderField(HDR_LOCATION);
+ assertTrue(location, location.startsWith(HTTPS));
+ }
+
+ @Test
+ public void testSslFilterWithAbsoluteRedirectURLWithoutScheme() throws Exception
+ {
+ String servletPath = "/test";
+ String redirectPath = String.format("//%s:%d/foo", this.serverAddress.getHostName(), this.serverAddress.getPort());
+
+ this.context.addServlet(new ServletHolder(new RedirectServlet(redirectPath)), servletPath);
+ this.server.start();
+
+ HttpURLConnection conn = openConnection(createURL(servletPath));
+
+ assertEquals(302, conn.getResponseCode());
+
+ String location = conn.getHeaderField(HDR_LOCATION);
+ assertTrue(location, location.startsWith(HTTPS));
+ }
+
+ @Test
+ public void testSslFilterWithAbsoluteRedirectURLWithHttpsScheme() throws Exception
+ {
+ String servletPath = "/test";
+ String redirectPath = String.format("https://%s:%d/foo", this.serverAddress.getHostName(), this.serverAddress.getPort());
+
+ this.context.addServlet(new ServletHolder(new RedirectServlet(redirectPath)), servletPath);
+ this.server.start();
+
+ HttpURLConnection conn = openConnection(createURL(servletPath));
+
+ assertEquals(302, conn.getResponseCode());
+
+ String location = conn.getHeaderField(HDR_LOCATION);
+ assertTrue(location, location.startsWith(HTTPS));
+ }
+
+ private HttpURLConnection openConnection(URL url) throws IOException
+ {
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestProperty(HDR_X_FORWARDED_PROTO, HTTPS);
+ conn.setRequestProperty(HDR_X_FORWARDED_SSL, "on");
+ conn.connect();
+ return conn;
+ }
+
+ private URL createURL(String path) throws MalformedURLException
+ {
+ return new URL(HTTP, this.serverAddress.getHostName(), this.serverAddress.getPort(), path);
+ }
+
+ private static class RedirectServlet extends HttpServlet
+ {
+ private final String redirectPath;
+
+ private RedirectServlet(String redirectPath)
+ {
+ this.redirectPath = redirectPath;
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ resp.sendRedirect(redirectPath);
+ assertEquals(HTTPS, req.getScheme());
+ }
+ }
+}
\ No newline at end of file
Propchange: felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterJettyTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java?rev=1635470&r1=1635469&r2=1635470&view=diff
==============================================================================
--- felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java (original)
+++ felix/trunk/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java Thu Oct 30 12:07:47 2014
@@ -42,6 +42,8 @@ public class SslFilterResponseTest
{
private static final String BACKEND_SERVER = "backend.server";
private static final String OTHER_SERVER = "other.server";
+
+ private static final String PATH = "http://localhost:8080/";
private static final String DEFAULT_HTTP_PORT = "80";
private static final String ALT_HTTP_PORT = "8080";
@@ -54,7 +56,7 @@ public class SslFilterResponseTest
public void testSetHttpLocationHeaderToNullValue() throws Exception
{
TestHttpServletResponse resp = createServletResponse();
- HttpServletRequest req = createServletRequest(BACKEND_SERVER);
+ HttpServletRequest req = createServletRequest(BACKEND_SERVER, PATH);
SslFilterResponse sresp = new SslFilterResponse(resp, req);
@@ -69,7 +71,7 @@ public class SslFilterResponseTest
String location, expected;
TestHttpServletResponse resp = createServletResponse();
- HttpServletRequest req = createServletRequest(BACKEND_SERVER);
+ HttpServletRequest req = createServletRequest(BACKEND_SERVER, PATH);
SslFilterResponse sresp = new SslFilterResponse(resp, req);
@@ -87,7 +89,7 @@ public class SslFilterResponseTest
String location, expected;
TestHttpServletResponse resp = createServletResponse();
- HttpServletRequest req = createServletRequest(BACKEND_SERVER);
+ HttpServletRequest req = createServletRequest(BACKEND_SERVER, PATH);
SslFilterResponse sresp = new SslFilterResponse(resp, req);
@@ -105,7 +107,7 @@ public class SslFilterResponseTest
String location, expected;
TestHttpServletResponse resp = createServletResponse();
- HttpServletRequest req = createServletRequest(BACKEND_SERVER);
+ HttpServletRequest req = createServletRequest(BACKEND_SERVER, PATH);
SslFilterResponse sresp = new SslFilterResponse(resp, req);
@@ -123,7 +125,7 @@ public class SslFilterResponseTest
String location, expected;
TestHttpServletResponse resp = createServletResponse();
- HttpServletRequest req = createServletRequest(BACKEND_SERVER, DEFAULT_HTTP_PORT, HTTPS, ALT_HTTPS_PORT);
+ HttpServletRequest req = createServletRequest(BACKEND_SERVER, DEFAULT_HTTP_PORT, HTTPS, ALT_HTTPS_PORT, PATH);
SslFilterResponse sresp = new SslFilterResponse(resp, req);
@@ -141,7 +143,7 @@ public class SslFilterResponseTest
String location, expected;
TestHttpServletResponse resp = createServletResponse();
- HttpServletRequest req = createServletRequest(BACKEND_SERVER);
+ HttpServletRequest req = createServletRequest(BACKEND_SERVER, PATH);
SslFilterResponse sresp = new SslFilterResponse(resp, req);
@@ -157,7 +159,7 @@ public class SslFilterResponseTest
public void testSetHttpLocationHeaderToOtherRequestURI() throws Exception
{
TestHttpServletResponse resp = createServletResponse();
- HttpServletRequest req = createServletRequest(BACKEND_SERVER);
+ HttpServletRequest req = createServletRequest(BACKEND_SERVER, PATH);
SslFilterResponse sresp = new SslFilterResponse(resp, req);
@@ -169,16 +171,17 @@ public class SslFilterResponseTest
assertEquals(expected, resp.getHeader(LOCATION));
}
- private HttpServletRequest createServletRequest(String serverName)
+ private HttpServletRequest createServletRequest(String serverName, String requestURL)
{
- return createServletRequest(serverName, DEFAULT_HTTP_PORT, HTTPS, DEFAULT_HTTPS_PORT);
+ return createServletRequest(serverName, DEFAULT_HTTP_PORT, HTTPS, DEFAULT_HTTPS_PORT, requestURL);
}
- private HttpServletRequest createServletRequest(String serverName, String serverPort, String forwardedProto, String forwardedPort)
+ private HttpServletRequest createServletRequest(String serverName, String serverPort, String forwardedProto, String forwardedPort, String requestURL)
{
HttpServletRequest req = mock(HttpServletRequest.class);
when(req.getServerName()).thenReturn(serverName);
when(req.getServerPort()).thenReturn(Integer.parseInt(serverPort));
+ when(req.getRequestURL()).thenReturn(new StringBuffer(requestURL));
when(req.getHeader("X-Forwarded-Proto")).thenReturn(forwardedProto);
when(req.getHeader("X-Forwarded-Port")).thenReturn(forwardedPort);
return req;