From 5f868b493a7ba63c2dc2622475ecc29f34e4346b Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Tue, 18 Jul 2017 14:31:56 -0500 Subject: [PATCH] Add ForwardedHeaderFilter requestOnly Add an option for ForwardedHeaderFilter to only process the HttpServletRequest. This means that HttpServletResponse.sendRedirect will only work when the application is conifgured to use relative redirects using Servlet Container specific setup. Issue: SPR-15717 --- .../web/filter/ForwardedHeaderFilter.java | 19 +++++++++++++++++- .../filter/ForwardedHeaderFilterTests.java | 20 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/spring-web/src/main/java/org/springframework/web/filter/ForwardedHeaderFilter.java b/spring-web/src/main/java/org/springframework/web/filter/ForwardedHeaderFilter.java index cce050a6cc..1751a699af 100644 --- a/spring-web/src/main/java/org/springframework/web/filter/ForwardedHeaderFilter.java +++ b/spring-web/src/main/java/org/springframework/web/filter/ForwardedHeaderFilter.java @@ -79,6 +79,8 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter { private boolean removeOnly; + private boolean requestOnly; + public ForwardedHeaderFilter() { this.pathHelper = new UrlPathHelper(); @@ -97,6 +99,20 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter { this.removeOnly = removeOnly; } + /** + * Enables mode in which only the HttpServletRequest is modified. This means that + * {@link HttpServletResponse#sendRedirect(String)} will only work when the application is configured to use + * relative redirects. This can be done with Servlet Container specific setup. For example, using Tomcat's + * useRelativeRedirects + * attribute. + * + * @param requestOnly whether to customize the {@code HttpServletResponse} or not. Default is false (customize the + * {@code HttpServletResponse}) + * @since 4.3.10 + */ + public void setRequestOnly(boolean requestOnly) { + this.requestOnly = requestOnly; + } @Override protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { @@ -130,7 +146,8 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter { } else { HttpServletRequest theRequest = new ForwardedHeaderExtractingRequest(request, this.pathHelper); - HttpServletResponse theResponse = new ForwardedHeaderExtractingResponse(response, theRequest); + HttpServletResponse theResponse = this.requestOnly ? response : + new ForwardedHeaderExtractingResponse(response, theRequest); filterChain.doFilter(theRequest, theResponse); } } diff --git a/spring-web/src/test/java/org/springframework/web/filter/ForwardedHeaderFilterTests.java b/spring-web/src/test/java/org/springframework/web/filter/ForwardedHeaderFilterTests.java index 2af2f108e3..fc23caa993 100644 --- a/spring-web/src/test/java/org/springframework/web/filter/ForwardedHeaderFilterTests.java +++ b/spring-web/src/test/java/org/springframework/web/filter/ForwardedHeaderFilterTests.java @@ -403,6 +403,26 @@ public class ForwardedHeaderFilterTests { assertEquals("../foo/bar", redirectedUrl); } + @Test + public void sendRedirectWhenRequestOnlyAndXForwardedThenUsesRelativeRedirects() throws Exception { + this.request.addHeader(X_FORWARDED_PROTO, "https"); + this.request.addHeader(X_FORWARDED_HOST, "example.com"); + this.request.addHeader(X_FORWARDED_PORT, "443"); + this.filter.setRequestOnly(true); + + String location = sendRedirect("/a"); + + assertEquals("/a", location); + } + + @Test + public void sendRedirectWhenRequestOnlyAndNoXForwardedThenUsesRelativeRedirects() throws Exception { + this.filter.setRequestOnly(true); + + String location = sendRedirect("/a"); + + assertEquals("/a", location); + } private String sendRedirect(final String location) throws ServletException, IOException { MockHttpServletResponse response = doWithFiltersAndGetResponse(this.filter, new OncePerRequestFilter() {