From 7ee687c79866f59b678c07f083b411e0a9b0d134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Wed, 1 Jun 2016 19:58:46 +1000 Subject: [PATCH] Support X-Forwarded-Prefix in ForwardedHeaderFilter See SPR-14270 --- .../web/filter/ForwardedHeaderFilter.java | 25 ++++++++++++- .../filter/ForwardedHeaderFilterTests.java | 37 +++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) 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 c21a3ac0c6..c16fb46f9b 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 @@ -34,6 +34,7 @@ import org.springframework.http.HttpRequest; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UrlPathHelper; @@ -48,6 +49,7 @@ import org.springframework.web.util.UrlPathHelper; * reflects the client-originated protocol and address. * * @author Rossen Stoyanchev + * @author EddĂș MelĂ©ndez * @since 4.3 */ public class ForwardedHeaderFilter extends OncePerRequestFilter { @@ -143,13 +145,32 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter { this.host = uriComponents.getHost(); this.port = (port == -1 ? (this.secure ? 443 : 80) : port); - this.contextPath = (pathHelper != null ? pathHelper.getContextPath(request) : request.getContextPath()); - this.requestUri = (pathHelper != null ? pathHelper.getRequestUri(request) : request.getRequestURI()); + this.contextPath = contextPath(request, pathHelper); + this.requestUri = requestUri(request, pathHelper); this.requestUrl = initRequestUrl(this.scheme, this.host, port, this.requestUri); this.headers = initHeaders(request); } + private static String contextPath(HttpServletRequest request, ContextPathHelper pathHelper) { + String contextPath = (pathHelper != null ? pathHelper.getContextPath(request) : request.getContextPath()); + return prependForwardedPrefix(request, contextPath); + } + + private static String requestUri(HttpServletRequest request, ContextPathHelper pathHelper) { + String requestUri = (pathHelper != null ? pathHelper.getRequestUri(request) : request.getRequestURI()); + return prependForwardedPrefix(request, requestUri); + } + + private static String prependForwardedPrefix(HttpServletRequest request, String value) { + String header = request.getHeader("X-Forwarded-Prefix"); + if (StringUtils.hasText(header)) { + value = header + value; + } + UriComponents uriComponents = UriComponentsBuilder.fromUriString(value).build(); + return uriComponents.toUriString(); + } + private static StringBuffer initRequestUrl(String scheme, String host, int port, String path) { StringBuffer sb = new StringBuffer(); sb.append(scheme).append("://").append(host); 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 bd7a375bd6..c6d54b22bd 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 @@ -170,6 +170,43 @@ public class ForwardedHeaderFilterTests { assertEquals("bar", actual.getHeader("foo")); } + @Test + public void requestUriWithForwardedPrefix() throws Exception { + this.request.addHeader("X-Forwarded-Prefix", "/prefix"); + this.request.setRequestURI("/mvc-showcase"); + + HttpServletRequest actual = filterAndGetWrappedRequest(); + assertEquals("http://localhost/prefix/mvc-showcase", actual.getRequestURL() + .toString()); + } + + @Test + public void requestUriWithForwardedPrefixTrailingSlash() throws Exception { + this.request.addHeader("X-Forwarded-Prefix", "/prefix/"); + this.request.setRequestURI("/mvc-showcase"); + + HttpServletRequest actual = filterAndGetWrappedRequest(); + assertEquals("http://localhost/prefix/mvc-showcase", actual.getRequestURL() + .toString()); + } + + @Test + public void contextPathWithForwardedPrefix() throws Exception { + this.request.addHeader("X-Forwarded-Prefix", "/prefix"); + this.request.setContextPath("/mvc-showcase"); + + String actual = filterAndGetContextPath(); + assertEquals("/prefix/mvc-showcase", actual); + } + + @Test + public void contextPathWithForwardedPrefixTrailingSlash() throws Exception { + this.request.addHeader("X-Forwarded-Prefix", "/prefix/"); + this.request.setContextPath("/mvc-showcase"); + + String actual = filterAndGetContextPath(); + assertEquals("/prefix/mvc-showcase", actual); + } private String filterAndGetContextPath() throws ServletException, IOException { return filterAndGetWrappedRequest().getContextPath();