diff --git a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java index 0370f01d14..7e04851647 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java +++ b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java @@ -677,7 +677,7 @@ public class UriComponentsBuilder implements Cloneable { String forwardedToUse = StringUtils.tokenizeToStringArray(forwardedHeader, ",")[0]; Matcher matcher = FORWARDED_HOST_PATTERN.matcher(forwardedToUse); if (matcher.find()) { - host(matcher.group(1).trim()); + adaptForwardedHost(matcher.group(1).trim()); } matcher = FORWARDED_PROTO_PATTERN.matcher(forwardedToUse); if (matcher.find()) { @@ -687,16 +687,7 @@ public class UriComponentsBuilder implements Cloneable { else { String hostHeader = headers.getFirst("X-Forwarded-Host"); if (StringUtils.hasText(hostHeader)) { - String hostToUse = StringUtils.tokenizeToStringArray(hostHeader, ",")[0]; - int portSeparatorIdx = hostToUse.lastIndexOf(":"); - if (portSeparatorIdx > hostToUse.lastIndexOf("]")) { - host(hostToUse.substring(0, portSeparatorIdx)); - port(Integer.parseInt(hostToUse.substring(portSeparatorIdx + 1))); - } - else { - host(hostToUse); - port(null); - } + adaptForwardedHost(StringUtils.tokenizeToStringArray(hostHeader, ",")[0]); } String portHeader = headers.getFirst("X-Forwarded-Port"); @@ -718,6 +709,18 @@ public class UriComponentsBuilder implements Cloneable { return this; } + private void adaptForwardedHost(String hostToUse) { + int portSeparatorIdx = hostToUse.lastIndexOf(":"); + if (portSeparatorIdx > hostToUse.lastIndexOf("]")) { + host(hostToUse.substring(0, portSeparatorIdx)); + port(Integer.parseInt(hostToUse.substring(portSeparatorIdx + 1))); + } + else { + host(hostToUse); + port(null); + } + } + private void resetHierarchicalComponents() { this.userInfo = null; this.host = null; diff --git a/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java b/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java index 546496c2c7..946a755ba8 100644 --- a/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java @@ -782,4 +782,59 @@ public class UriComponentsBuilderTests { assertEquals("/rest/mobile/users/1", result.getPath()); } + @Test + public void fromHttpRequestForwardedHeaderWithHostPortAndWithoutServerPort() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("Forwarded", "proto=https; host=84.198.58.199:9090"); + request.setScheme("http"); + request.setServerName("example.com"); + request.setRequestURI("/rest/mobile/users/1"); + + HttpRequest httpRequest = new ServletServerHttpRequest(request); + UriComponents result = UriComponentsBuilder.fromHttpRequest(httpRequest).build(); + + assertEquals("https", result.getScheme()); + assertEquals("84.198.58.199", result.getHost()); + assertEquals("/rest/mobile/users/1", result.getPath()); + assertEquals(9090, result.getPort()); + assertEquals("https://84.198.58.199:9090/rest/mobile/users/1", result.toUriString()); + } + + @Test + public void fromHttpRequestForwardedHeaderWithHostPortAndServerPort() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("Forwarded", "proto=https; host=84.198.58.199:9090"); + request.setScheme("http"); + request.setServerPort(8080); + request.setServerName("example.com"); + request.setRequestURI("/rest/mobile/users/1"); + + HttpRequest httpRequest = new ServletServerHttpRequest(request); + UriComponents result = UriComponentsBuilder.fromHttpRequest(httpRequest).build(); + + assertEquals("https", result.getScheme()); + assertEquals("84.198.58.199", result.getHost()); + assertEquals("/rest/mobile/users/1", result.getPath()); + assertEquals(9090, result.getPort()); + assertEquals("https://84.198.58.199:9090/rest/mobile/users/1", result.toUriString()); + } + + @Test + public void fromHttpRequestForwardedHeaderWithoutHostPortAndWithServerPort() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("Forwarded", "proto=https; host=84.198.58.199"); + request.setScheme("http"); + request.setServerPort(8080); + request.setServerName("example.com"); + request.setRequestURI("/rest/mobile/users/1"); + + HttpRequest httpRequest = new ServletServerHttpRequest(request); + UriComponents result = UriComponentsBuilder.fromHttpRequest(httpRequest).build(); + + assertEquals("https", result.getScheme()); + assertEquals("84.198.58.199", result.getHost()); + assertEquals("/rest/mobile/users/1", result.getPath()); + assertEquals(-1, result.getPort()); + assertEquals("https://84.198.58.199/rest/mobile/users/1", result.toUriString()); + } }