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() {