From ec55e429f0f59da12ce9553d163d4361b4fffae0 Mon Sep 17 00:00:00 2001 From: Gregory Vandenbroucke Date: Fri, 28 Apr 2017 20:36:13 +0200 Subject: [PATCH] Full "Forwarded" header support including port number Issue: SPR-15504 --- .../web/util/UriComponentsBuilder.java | 11 +++- .../web/util/UriComponentsBuilderTests.java | 55 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) 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 324b77d2a0..1338148443 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 @@ -717,7 +717,16 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable { String forwardedToUse = StringUtils.tokenizeToStringArray(forwardedHeader, ",")[0]; Matcher matcher = FORWARDED_HOST_PATTERN.matcher(forwardedToUse); if (matcher.find()) { - host(matcher.group(1).trim()); + String hostToUse = matcher.group(1).trim(); + 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); + } } matcher = FORWARDED_PROTO_PATTERN.matcher(forwardedToUse); if (matcher.find()) { 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 8322d5132b..9bb4995723 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 @@ -790,4 +790,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()); + } }