Merge pull request #1071 from eddumelendez/SPR-14270
This commit is contained in:
@@ -34,20 +34,23 @@ import org.springframework.http.HttpRequest;
|
|||||||
import org.springframework.http.server.ServletServerHttpRequest;
|
import org.springframework.http.server.ServletServerHttpRequest;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.util.UriComponents;
|
import org.springframework.web.util.UriComponents;
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
import org.springframework.web.util.UrlPathHelper;
|
import org.springframework.web.util.UrlPathHelper;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter that wraps the request in order to override its
|
* Filter that wraps the request in order to override its
|
||||||
* {@link HttpServletRequest#getServerName() getServerName()},
|
* {@link HttpServletRequest#getServerName() getServerName()},
|
||||||
* {@link HttpServletRequest#getServerPort() getServerPort()},
|
* {@link HttpServletRequest#getServerPort() getServerPort()},
|
||||||
* {@link HttpServletRequest#getScheme() getScheme()}, and
|
* {@link HttpServletRequest#getScheme() getScheme()}, and
|
||||||
* {@link HttpServletRequest#isSecure() isSecure()} methods with values derived
|
* {@link HttpServletRequest#isSecure() isSecure()} methods with values derived
|
||||||
* from "Fowarded" or "X-Forwarded-*" headers. In effect the wrapped request
|
* from "Forwarded" or "X-Forwarded-*" headers. In effect the wrapped request
|
||||||
* reflects the client-originated protocol and address.
|
* reflects the client-originated protocol and address.
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
* @author Eddú Meléndez
|
||||||
* @since 4.3
|
* @since 4.3
|
||||||
*/
|
*/
|
||||||
public class ForwardedHeaderFilter extends OncePerRequestFilter {
|
public class ForwardedHeaderFilter extends OncePerRequestFilter {
|
||||||
@@ -55,11 +58,12 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
|
|||||||
private static final Set<String> FORWARDED_HEADER_NAMES;
|
private static final Set<String> FORWARDED_HEADER_NAMES;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
FORWARDED_HEADER_NAMES = new HashSet<String>(4);
|
FORWARDED_HEADER_NAMES = new HashSet<String>(5);
|
||||||
FORWARDED_HEADER_NAMES.add("Forwarded");
|
FORWARDED_HEADER_NAMES.add("Forwarded");
|
||||||
FORWARDED_HEADER_NAMES.add("X-Forwarded-Host");
|
FORWARDED_HEADER_NAMES.add("X-Forwarded-Host");
|
||||||
FORWARDED_HEADER_NAMES.add("X-Forwarded-Port");
|
FORWARDED_HEADER_NAMES.add("X-Forwarded-Port");
|
||||||
FORWARDED_HEADER_NAMES.add("X-Forwarded-Proto");
|
FORWARDED_HEADER_NAMES.add("X-Forwarded-Proto");
|
||||||
|
FORWARDED_HEADER_NAMES.add("X-Forwarded-Prefix");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -131,6 +135,7 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
|
|||||||
|
|
||||||
private final Map<String, List<String>> headers;
|
private final Map<String, List<String>> headers;
|
||||||
|
|
||||||
|
|
||||||
public ForwardedHeaderRequestWrapper(HttpServletRequest request, ContextPathHelper pathHelper) {
|
public ForwardedHeaderRequestWrapper(HttpServletRequest request, ContextPathHelper pathHelper) {
|
||||||
super(request);
|
super(request);
|
||||||
|
|
||||||
@@ -143,13 +148,23 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
|
|||||||
this.host = uriComponents.getHost();
|
this.host = uriComponents.getHost();
|
||||||
this.port = (port == -1 ? (this.secure ? 443 : 80) : port);
|
this.port = (port == -1 ? (this.secure ? 443 : 80) : port);
|
||||||
|
|
||||||
this.contextPath = (pathHelper != null ? pathHelper.getContextPath(request) : request.getContextPath());
|
this.contextPath = initContextPath(request, pathHelper);
|
||||||
this.requestUri = (pathHelper != null ? pathHelper.getRequestUri(request) : request.getRequestURI());
|
this.requestUri = initRequestUri(request, pathHelper);
|
||||||
this.requestUrl = initRequestUrl(this.scheme, this.host, port, this.requestUri);
|
this.requestUrl = initRequestUrl(this.scheme, this.host, port, this.requestUri);
|
||||||
|
|
||||||
this.headers = initHeaders(request);
|
this.headers = initHeaders(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static String initContextPath(HttpServletRequest request, ContextPathHelper pathHelper) {
|
||||||
|
String contextPath = (pathHelper != null ? pathHelper.getContextPath(request) : request.getContextPath());
|
||||||
|
return prependForwardedPrefix(request, contextPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String initRequestUri(HttpServletRequest request, ContextPathHelper pathHelper) {
|
||||||
|
String requestUri = (pathHelper != null ? pathHelper.getRequestUri(request) : request.getRequestURI());
|
||||||
|
return prependForwardedPrefix(request, requestUri);
|
||||||
|
}
|
||||||
|
|
||||||
private static StringBuffer initRequestUrl(String scheme, String host, int port, String path) {
|
private static StringBuffer initRequestUrl(String scheme, String host, int port, String path) {
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
sb.append(scheme).append("://").append(host);
|
sb.append(scheme).append("://").append(host);
|
||||||
@@ -174,6 +189,17 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
|
|||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String prependForwardedPrefix(HttpServletRequest request, String value) {
|
||||||
|
String header = request.getHeader("X-Forwarded-Prefix");
|
||||||
|
if (StringUtils.hasText(header)) {
|
||||||
|
while (header.endsWith("/")) {
|
||||||
|
header = header.substring(0, header.length() - 1);
|
||||||
|
}
|
||||||
|
value = header + value;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getScheme() {
|
public String getScheme() {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import static org.junit.Assert.assertTrue;
|
|||||||
/**
|
/**
|
||||||
* Unit tests for {@link ForwardedHeaderFilter}.
|
* Unit tests for {@link ForwardedHeaderFilter}.
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
* @author Eddú Meléndez
|
||||||
*/
|
*/
|
||||||
public class ForwardedHeaderFilterTests {
|
public class ForwardedHeaderFilterTests {
|
||||||
|
|
||||||
@@ -170,6 +171,41 @@ public class ForwardedHeaderFilterTests {
|
|||||||
assertEquals("bar", actual.getHeader("foo"));
|
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 {
|
private String filterAndGetContextPath() throws ServletException, IOException {
|
||||||
return filterAndGetWrappedRequest().getContextPath();
|
return filterAndGetWrappedRequest().getContextPath();
|
||||||
|
|||||||
Reference in New Issue
Block a user