diff --git a/spring-web/src/main/java/org/springframework/web/util/ForwardedHeaderUtils.java b/spring-web/src/main/java/org/springframework/web/util/ForwardedHeaderUtils.java index acb84a14568..db7453249a3 100644 --- a/spring-web/src/main/java/org/springframework/web/util/ForwardedHeaderUtils.java +++ b/spring-web/src/main/java/org/springframework/web/util/ForwardedHeaderUtils.java @@ -56,6 +56,163 @@ public abstract class ForwardedHeaderUtils { private static final Pattern FORWARDED_BY_PATTERN = Pattern.compile("(?i:by)=" + FORWARDED_VALUE); + /** + * Parse the "Forwarded" header. + * @param uri the request {@code URI} + * @param headers the HTTP headers to get the "Forwarded" header from + * @param remoteAddress for a default port for the parsed "for" value + * @param localAddress for a default port for the parsed "by" value + * @return a {@link ForwardedInfo} with the parse results + * @since 7.1 + * @see RFC 7239 + */ + public static ForwardedInfo parseForwardedHeader(URI uri, HttpHeaders headers, + @Nullable InetSocketAddress remoteAddress, @Nullable InetSocketAddress localAddress) { + + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUri(uri); + InetSocketAddress forAddress = null; + InetSocketAddress byAddress = null; + + String forwardedHeader = headers.getFirst("Forwarded"); + if (StringUtils.hasText(forwardedHeader)) { + String forwardedToUse = getLeftMostValue(forwardedHeader); + + Matcher matcher = FORWARDED_PROTO_PATTERN.matcher(forwardedToUse); + if (matcher.find()) { + uriComponentsBuilder.scheme(matcher.group(1).trim()); + uriComponentsBuilder.port(null); + } + matcher = FORWARDED_HOST_PATTERN.matcher(forwardedToUse); + if (matcher.find()) { + adaptForwardedHost(uriComponentsBuilder, matcher.group(1).trim()); + } + uriComponentsBuilder.resetPortIfDefaultForScheme(); + + matcher = FORWARDED_FOR_PATTERN.matcher(forwardedToUse); + if (matcher.find()) { + forAddress = parseInetSocketAddress(matcher.group(1).trim(), getPortToUse(remoteAddress, uri)); + } + + matcher = FORWARDED_BY_PATTERN.matcher(forwardedToUse); + if (matcher.find()) { + byAddress = parseInetSocketAddress(matcher.group(1).trim(), getPortToUse(localAddress, uri)); + } + } + + return new ForwardedInfo(uriComponentsBuilder, forAddress, byAddress); + } + + /** + * Parse the "X-Forwarded-Proto", "X-Forwarded-Host", "X-Forwarded-Port", and + * "X-Forwarded-For" headers, the alternative to the "Forwarded" header. + *
There is no parsing of "X-Forwarded-By" currently, so the + * {@code byAddress} in {@link ForwardedInfo} is always {@code null}. + * @param uri the request {@code URI} + * @param headers the HTTP headers to get the "Forwarded" header from + * @param remoteAddress for a default port for the parsed "for" value + * @param localAddress for a default port for the parsed "by" value + * @return a {@link ForwardedInfo} with the scheme, host, and port adapted + * from the "X-Forwarded-*" headers, and the parsed "for" address + * @since 7.1 + */ + public static ForwardedInfo parseXForwardedHeaders(URI uri, HttpHeaders headers, + @Nullable InetSocketAddress remoteAddress, @Nullable InetSocketAddress localAddress) { + + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUri(uri); + + String protocolHeader = headers.getFirst("X-Forwarded-Proto"); + if (StringUtils.hasText(protocolHeader)) { + uriComponentsBuilder.scheme(getLeftMostValue(protocolHeader)); + uriComponentsBuilder.port(null); + } + else if (isForwardedSslOn(headers)) { + uriComponentsBuilder.scheme("https"); + uriComponentsBuilder.port(null); + } + String hostHeader = headers.getFirst("X-Forwarded-Host"); + if (StringUtils.hasText(hostHeader)) { + adaptForwardedHost(uriComponentsBuilder, getLeftMostValue(hostHeader)); + } + String portHeader = headers.getFirst("X-Forwarded-Port"); + if (StringUtils.hasText(portHeader)) { + try { + uriComponentsBuilder.port(Integer.parseInt(getLeftMostValue(portHeader))); + } + catch (NumberFormatException ex) { + throw new IllegalArgumentException("Failed to parse \"X-Forwarded-Port: " + portHeader + "\""); + } + } + uriComponentsBuilder.resetPortIfDefaultForScheme(); + + InetSocketAddress forAddress = null; + String forHeader = headers.getFirst("X-Forwarded-For"); + if (StringUtils.hasText(forHeader)) { + String host = getLeftMostValue(forHeader); + boolean ipv6 = (host.indexOf(':') != -1); + host = (ipv6 && !host.startsWith("[") && !host.endsWith("]") ? "[" + host + "]" : host); + int port = getPortToUse(remoteAddress, uri); + forAddress = InetSocketAddress.createUnresolved(host, port); + } + + return new ForwardedInfo(uriComponentsBuilder, forAddress, null); + } + + private static String getLeftMostValue(String headerValue) { + return StringUtils.tokenizeToStringArray(headerValue, ",")[0]; + } + + private static boolean isForwardedSslOn(HttpHeaders headers) { + String forwardedSsl = headers.getFirst("X-Forwarded-Ssl"); + return (StringUtils.hasText(forwardedSsl) && forwardedSsl.equalsIgnoreCase("on")); + } + + private static void adaptForwardedHost(UriComponentsBuilder uriComponentsBuilder, String rawValue) { + int portSeparatorIdx = rawValue.lastIndexOf(':'); + int squareBracketIdx = rawValue.lastIndexOf(']'); + if (portSeparatorIdx > squareBracketIdx) { + if (squareBracketIdx == -1 && rawValue.indexOf(':') != portSeparatorIdx) { + throw new IllegalArgumentException("Invalid IPv4 address: " + rawValue); + } + uriComponentsBuilder.host(rawValue.substring(0, portSeparatorIdx)); + try { + uriComponentsBuilder.port( + Integer.parseInt(rawValue, portSeparatorIdx + 1, rawValue.length(), 10)); + } + catch (NumberFormatException ex) { + throw new IllegalArgumentException( + "Failed to parse port in forwarded host value: " + rawValue + "\""); + } + } + else { + uriComponentsBuilder.host(rawValue); + uriComponentsBuilder.port(null); + } + } + + private static int getPortToUse(@Nullable InetSocketAddress address, URI uri) { + return (address != null ? address.getPort() : "https".equals(uri.getScheme()) ? 443 : 80); + } + + private static InetSocketAddress parseInetSocketAddress(String value, int port) { + String host = value; + int portSeparatorIdx = value.lastIndexOf(':'); + int squareBracketIdx = value.lastIndexOf(']'); + if (portSeparatorIdx > squareBracketIdx) { + if (squareBracketIdx == -1 && value.indexOf(':') != portSeparatorIdx) { + throw new IllegalArgumentException("Invalid IPv4 address: " + value); + } + host = value.substring(0, portSeparatorIdx); + try { + port = Integer.parseInt(value, portSeparatorIdx + 1, value.length(), 10); + } + catch (NumberFormatException ex) { + throw new IllegalArgumentException( + "Failed to parse port in forwarded address value: " + value); + } + } + return InetSocketAddress.createUnresolved(host, port); + } + /** * Adapt the scheme+host+port of the given {@link URI} from the "Forwarded" header * (see RFC 7239) or from the @@ -88,7 +245,7 @@ public abstract class ForwardedHeaderUtils { else { String protocolHeader = headers.getFirst("X-Forwarded-Proto"); if (StringUtils.hasText(protocolHeader)) { - uriComponentsBuilder.scheme(StringUtils.tokenizeToStringArray(protocolHeader, ",")[0]); + uriComponentsBuilder.scheme(getLeftMostValue(protocolHeader)); uriComponentsBuilder.port(null); } else if (isForwardedSslOn(headers)) { @@ -97,11 +254,11 @@ public abstract class ForwardedHeaderUtils { } String hostHeader = headers.getFirst("X-Forwarded-Host"); if (StringUtils.hasText(hostHeader)) { - adaptForwardedHost(uriComponentsBuilder, StringUtils.tokenizeToStringArray(hostHeader, ",")[0]); + adaptForwardedHost(uriComponentsBuilder, getLeftMostValue(hostHeader)); } String portHeader = headers.getFirst("X-Forwarded-Port"); if (StringUtils.hasText(portHeader)) { - uriComponentsBuilder.port(Integer.parseInt(StringUtils.tokenizeToStringArray(portHeader, ",")[0])); + uriComponentsBuilder.port(Integer.parseInt(getLeftMostValue(portHeader))); } } } @@ -116,27 +273,6 @@ public abstract class ForwardedHeaderUtils { return uriComponentsBuilder; } - private static boolean isForwardedSslOn(HttpHeaders headers) { - String forwardedSsl = headers.getFirst("X-Forwarded-Ssl"); - return StringUtils.hasText(forwardedSsl) && forwardedSsl.equalsIgnoreCase("on"); - } - - private static void adaptForwardedHost(UriComponentsBuilder uriComponentsBuilder, String rawValue) { - int portSeparatorIdx = rawValue.lastIndexOf(':'); - int squareBracketIdx = rawValue.lastIndexOf(']'); - if (portSeparatorIdx > squareBracketIdx) { - if (squareBracketIdx == -1 && rawValue.indexOf(':') != portSeparatorIdx) { - throw new IllegalArgumentException("Invalid IPv4 address: " + rawValue); - } - uriComponentsBuilder.host(rawValue.substring(0, portSeparatorIdx)); - uriComponentsBuilder.port(Integer.parseInt(rawValue, portSeparatorIdx + 1, rawValue.length(), 10)); - } - else { - uriComponentsBuilder.host(rawValue); - uriComponentsBuilder.port(null); - } - } - /** * Parse the first "Forwarded: for=..." or "X-Forwarded-For" header value to * an {@code InetSocketAddress} representing the address of the client. @@ -150,25 +286,22 @@ public abstract class ForwardedHeaderUtils { public static @Nullable InetSocketAddress parseForwardedFor( URI uri, HttpHeaders headers, @Nullable InetSocketAddress remoteAddress) { - int port = (remoteAddress != null ? - remoteAddress.getPort() : "https".equals(uri.getScheme()) ? 443 : 80); - String forwardedHeader = headers.getFirst("Forwarded"); if (StringUtils.hasText(forwardedHeader)) { - String forwardedToUse = StringUtils.tokenizeToStringArray(forwardedHeader, ",")[0]; + String forwardedToUse = getLeftMostValue(forwardedHeader); Matcher matcher = FORWARDED_FOR_PATTERN.matcher(forwardedToUse); if (matcher.find()) { String value = matcher.group(1).trim(); - return parseInetSocketAddress(value, port); + return parseInetSocketAddress(value, getPortToUse(remoteAddress, uri)); } } String forHeader = headers.getFirst("X-Forwarded-For"); if (StringUtils.hasText(forHeader)) { - String host = StringUtils.tokenizeToStringArray(forHeader, ",")[0]; + String host = getLeftMostValue(forHeader); boolean ipv6 = (host.indexOf(':') != -1); host = (ipv6 && !host.startsWith("[") && !host.endsWith("]") ? "[" + host + "]" : host); - return InetSocketAddress.createUnresolved(host, port); + return InetSocketAddress.createUnresolved(host, getPortToUse(remoteAddress, uri)); } return null; @@ -188,40 +321,34 @@ public abstract class ForwardedHeaderUtils { public static @Nullable InetSocketAddress parseForwardedBy( URI uri, HttpHeaders headers, @Nullable InetSocketAddress localAddress) { - int port = (localAddress != null ? - localAddress.getPort() : "https".equals(uri.getScheme()) ? 443 : 80); - String forwardedHeader = headers.getFirst("Forwarded"); if (StringUtils.hasText(forwardedHeader)) { - String forwardedToUse = StringUtils.tokenizeToStringArray(forwardedHeader, ",")[0]; + String forwardedToUse = getLeftMostValue(forwardedHeader); Matcher matcher = FORWARDED_BY_PATTERN.matcher(forwardedToUse); if (matcher.find()) { String value = matcher.group(1).trim(); - return parseInetSocketAddress(value, port); + return parseInetSocketAddress(value, getPortToUse(localAddress, uri)); } } return null; } - private static InetSocketAddress parseInetSocketAddress(String value, int port) { - String host = value; - int portSeparatorIdx = value.lastIndexOf(':'); - int squareBracketIdx = value.lastIndexOf(']'); - if (portSeparatorIdx > squareBracketIdx) { - if (squareBracketIdx == -1 && value.indexOf(':') != portSeparatorIdx) { - throw new IllegalArgumentException("Invalid IPv4 address: " + value); - } - host = value.substring(0, portSeparatorIdx); - try { - port = Integer.parseInt(value, portSeparatorIdx + 1, value.length(), 10); - } - catch (NumberFormatException ex) { - throw new IllegalArgumentException( - "Failed to parse a port from \"forwarded\"-type header value: " + value); - } - } - return InetSocketAddress.createUnresolved(host, port); + + /** + * Container for the combined results of parsing either the "Forwarded" + * header or the "X-Forwarded-*" alternative headers. + * @since 7.1 + * @param uriComponentsBuilder the request URI adapted with the scheme, host, + * and port from forwarded header values + * @param forAddress the address parsed from the "Forwarded" header "for" or + * "X-Forwarded-For" value, representing the client, or {@code null} if not present + * @param byAddress the address parsed from the "Forwarded" header "by", + * representing the server, or {@code null} if not present; + * always {@code null} when returned from {@link #parseXForwardedHeaders} + */ + public record ForwardedInfo(UriComponentsBuilder uriComponentsBuilder, + @Nullable InetSocketAddress forAddress, @Nullable InetSocketAddress byAddress) { } } diff --git a/spring-web/src/test/java/org/springframework/web/util/ForwardedHeaderUtilsTests.java b/spring-web/src/test/java/org/springframework/web/util/ForwardedHeaderUtilsTests.java index 40fdd7a5ca4..71b03dce773 100644 --- a/spring-web/src/test/java/org/springframework/web/util/ForwardedHeaderUtilsTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/ForwardedHeaderUtilsTests.java @@ -51,7 +51,7 @@ class ForwardedHeaderUtilsTests { request.setQueryString("a=1"); ServletServerHttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getScheme()).isEqualTo("http"); assertThat(result.getHost()).isEqualTo("localhost"); assertThat(result.getPort()).isEqualTo(-1); @@ -72,7 +72,7 @@ class ForwardedHeaderUtilsTests { request.setRequestURI("/rest/mobile/users/1"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getScheme()).isEqualTo(protocol); assertThat(result.getHost()).isEqualTo("84.198.58.199"); @@ -93,7 +93,7 @@ class ForwardedHeaderUtilsTests { request.setRequestURI("/path"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getScheme()).isEqualTo(protocol); assertThat(result.getHost()).isEqualTo("84.198.58.199"); @@ -111,7 +111,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("Forwarded", "host=192.168.0.1"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromForwardedHeader(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.toString()).isEqualTo("https://192.168.0.1/mvc-showcase"); } @@ -126,7 +126,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("Forwarded", "host=[1abc:2abc:3abc::5ABC:6abc]"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromForwardedHeader(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.toString()).isEqualTo("http://[1abc:2abc:3abc::5ABC:6abc]/mvc-showcase"); } @@ -141,7 +141,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("X-Forwarded-Host", "[1abc:2abc:3abc::5ABC:6abc]"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.toString()).isEqualTo("http://[1abc:2abc:3abc::5ABC:6abc]/mvc-showcase"); } @@ -156,7 +156,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("X-Forwarded-Host", "[1abc:2abc:3abc::5ABC:6abc]:8080"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.toString()).isEqualTo("http://[1abc:2abc:3abc::5ABC:6abc]:8080/mvc-showcase"); } @@ -172,8 +172,7 @@ class ForwardedHeaderUtilsTests { HttpRequest httpRequest = new ServletServerHttpRequest(request); - assertThatThrownBy(() -> - ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build()) + assertThatThrownBy(() -> adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders())) .isInstanceOf(IllegalArgumentException.class); } @@ -187,7 +186,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("X-Forwarded-Host", "anotherHost"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.toString()).isEqualTo("https://anotherHost/mvc-showcase"); } @@ -202,7 +201,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("X-Forwarded-Host", "webtest.foo.bar.com:443"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getHost()).isEqualTo("webtest.foo.bar.com"); assertThat(result.getPort()).isEqualTo(443); @@ -217,7 +216,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("X-Forwarded-Host", "a.example.org, b.example.org, c.example.org"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getHost()).isEqualTo("a.example.org"); assertThat(result.getPort()).isEqualTo(-1); @@ -233,7 +232,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("X-Forwarded-Port", "9090"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getHost()).isEqualTo("foobarhost"); assertThat(result.getPort()).isEqualTo(9090); @@ -248,7 +247,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("X-Forwarded-Host", "example.org"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getHost()).isEqualTo("example.org"); assertThat(result.getPort()).isEqualTo(-1); @@ -263,7 +262,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("X-Forwarded-Proto", "https"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getScheme()).isEqualTo("https"); assertThat(result.getHost()).isEqualTo("example.org"); @@ -279,7 +278,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("X-Forwarded-Ssl", "on"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getScheme()).isEqualTo("https"); assertThat(result.getHost()).isEqualTo("example.org"); @@ -296,7 +295,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("X-Forwarded-Proto", "https"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getHost()).isEqualTo("example.org"); assertThat(result.getScheme()).isEqualTo("https"); @@ -315,7 +314,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("X-Forwarded-Port", "443"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.toString()).isEqualTo("https://84.198.58.199/mvc-showcase"); } @@ -331,7 +330,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("X-Forwarded-Port", "80,52022"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.toString()).isEqualTo("http://a.example.org/mvc-showcase"); } @@ -348,7 +347,7 @@ class ForwardedHeaderUtilsTests { request.addHeader("X-Forwarded-Proto", "https,https"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.toString()).isEqualTo("https://a.example.org/mvc-showcase"); } @@ -376,7 +375,7 @@ class ForwardedHeaderUtilsTests { return new HttpHeaders(); } }; - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(request.getURI(), request.getHeaders()).build(); + UriComponents result = adaptFromXForwardedHeaders(request.getURI(), request.getHeaders()); assertThat(result.toString()).isEqualTo("/"); } @@ -390,7 +389,7 @@ class ForwardedHeaderUtilsTests { request.setRequestURI("/rest/mobile/users/1"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromForwardedHeader(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getScheme()).isEqualTo("https"); assertThat(result.getHost()).isEqualTo("84.198.58.199"); @@ -406,7 +405,7 @@ class ForwardedHeaderUtilsTests { request.setRequestURI("/rest/mobile/users/1"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromForwardedHeader(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getScheme()).isEqualTo("https"); assertThat(result.getHost()).isEqualTo("84.198.58.199"); @@ -423,7 +422,7 @@ class ForwardedHeaderUtilsTests { request.setRequestURI("/rest/mobile/users/1"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromForwardedHeader(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getScheme()).isEqualTo("https"); assertThat(result.getHost()).isEqualTo("84.198.58.199"); @@ -439,7 +438,7 @@ class ForwardedHeaderUtilsTests { request.setRequestURI("/rest/mobile/users/1"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromForwardedHeader(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getScheme()).isEqualTo("https"); assertThat(result.getHost()).isEqualTo("84.198.58.199"); @@ -455,7 +454,7 @@ class ForwardedHeaderUtilsTests { request.setRequestURI("/rest/mobile/users/1"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromForwardedHeader(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getScheme()).isEqualTo("https"); assertThat(result.getHost()).isEqualTo("84.198.58.199"); @@ -474,7 +473,7 @@ class ForwardedHeaderUtilsTests { request.setRequestURI("/rest/mobile/users/1"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromForwardedHeader(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getScheme()).isEqualTo("https"); assertThat(result.getHost()).isEqualTo("84.198.58.199"); @@ -493,7 +492,7 @@ class ForwardedHeaderUtilsTests { request.setRequestURI("/rest/mobile/users/1"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromForwardedHeader(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getScheme()).isEqualTo("https"); assertThat(result.getHost()).isEqualTo("84.198.58.199"); @@ -512,7 +511,7 @@ class ForwardedHeaderUtilsTests { request.setRequestURI("/rest/mobile/users/1"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + UriComponents result = adaptFromForwardedHeader(httpRequest.getURI(), httpRequest.getHeaders()); assertThat(result.getScheme()).isEqualTo("https"); assertThat(result.getHost()).isEqualTo("example.com"); @@ -531,13 +530,17 @@ class ForwardedHeaderUtilsTests { request.setRequestURI("/rest/mobile/users/1"); HttpRequest httpRequest = new ServletServerHttpRequest(request); - UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); + ForwardedHeaderUtils.ForwardedInfo info = + ForwardedHeaderUtils.parseForwardedHeader(httpRequest.getURI(), httpRequest.getHeaders(), null, null); - assertThat(result.getScheme()).isEqualTo("https"); - assertThat(result.getHost()).isEqualTo("192.0.2.3"); + assertThat(info.forAddress()).isNotNull(); + assertThat(info.forAddress().getHostString()).isEqualTo("192.0.2.0"); + + UriComponents result = info.uriComponentsBuilder().build(); + assertThat(result.getScheme()).isEqualTo("http"); + assertThat(result.getHost()).isEqualTo("example.com"); assertThat(result.getPath()).isEqualTo("/rest/mobile/users/1"); - assertThat(result.getPort()).isEqualTo(9090); - assertThat(result.toUriString()).isEqualTo("https://192.0.2.3:9090/rest/mobile/users/1"); + assertThat(result.getPort()).isEqualTo(8080); } @Test // gh-34253 @@ -545,8 +548,8 @@ class ForwardedHeaderUtilsTests { HttpHeaders headers = new HttpHeaders(); headers.add("X-Forwarded-For", "fd00:fefe:1::4, 192.168.0.1"); - InetSocketAddress address = - ForwardedHeaderUtils.parseForwardedFor(URI.create("https://example.com"), headers, null); + InetSocketAddress address = ForwardedHeaderUtils.parseXForwardedHeaders( + URI.create("https://example.com"), headers, null, null).forAddress(); assertThat(address.getHostName()).isEqualTo("[fd00:fefe:1::4]"); } @@ -556,10 +559,21 @@ class ForwardedHeaderUtilsTests { HttpHeaders headers = new HttpHeaders(); headers.add("Forwarded", "by=[fd00:fefe:1::4], 192.168.0.1"); - InetSocketAddress address = - ForwardedHeaderUtils.parseForwardedBy(URI.create("https://example.com"), headers, null); + InetSocketAddress address = ForwardedHeaderUtils.parseForwardedHeader( + URI.create("https://example.com"), headers, null, null).byAddress(); assertThat(address.getHostName()).isEqualTo("[fd00:fefe:1::4]"); } + + private static UriComponents adaptFromForwardedHeader(URI uri, HttpHeaders headers) { + return ForwardedHeaderUtils.parseForwardedHeader(uri, headers, null, null) + .uriComponentsBuilder().build(); + } + + private static UriComponents adaptFromXForwardedHeaders(URI uri, HttpHeaders headers) { + return ForwardedHeaderUtils.parseXForwardedHeaders(uri, headers, null, null) + .uriComponentsBuilder().build(); + } + }