Add ForwardedInfo to ForwardedHeaderUtils

This commit adds two new methods in ForwardedHeaderUtils, one to parse
the standard "Forwarded" header only, and another to parse the
"X-Forwarded-*" alternative headers. As those are single parse methods,
a ForwardedInfo container type is necessary to return the results.

See gh-36964
This commit is contained in:
rstoyanchev
2026-07-23 12:15:24 +03:00
parent 224522244f
commit 7b71df72e5
2 changed files with 233 additions and 92 deletions
@@ -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 <a href="https://tools.ietf.org/html/rfc7239">RFC 7239</a>
*/
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.
* <p>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 <a href="https://tools.ietf.org/html/rfc7239">RFC 7239</a>) 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) {
}
}
@@ -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();
}
}