7 changed files with 797 additions and 669 deletions
@ -0,0 +1,190 @@
@@ -0,0 +1,190 @@
|
||||
/* |
||||
* Copyright 2002-2023 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.web.util; |
||||
|
||||
import java.net.InetSocketAddress; |
||||
import java.net.URI; |
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
|
||||
import org.springframework.http.HttpHeaders; |
||||
import org.springframework.lang.Nullable; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
|
||||
/** |
||||
* Utility class to assist with processing "Forwarded" and "X-Forwarded-*" headers. |
||||
* |
||||
* <p><strong>Note:</strong>There are security considerations surrounding the use |
||||
* of forwarded headers. Those should not be used unless the application is |
||||
* behind a trusted proxy that inserts them and also explicitly removes any such |
||||
* headers coming from an external source. |
||||
* |
||||
* <p>In most cases, should not use this class directly but rely on |
||||
* {@link org.springframework.web.filter.ForwardedHeaderFilter} for Spring MVC, or |
||||
* {@link org.springframework.web.server.adapter.ForwardedHeaderTransformer} in |
||||
* order to extract the information from them as early as possible, and discard |
||||
* such headers. Underlying servers such as Tomcat, Jetty, Reactor Netty, also |
||||
* provides options to handle forwarded headers even earlier. |
||||
* |
||||
* @author Rossen Stoyanchev |
||||
* @since 6.1 |
||||
*/ |
||||
public abstract class ForwardedHeaderUtils { |
||||
|
||||
private static final String FORWARDED_VALUE = "\"?([^;,\"]+)\"?"; |
||||
|
||||
private static final Pattern FORWARDED_HOST_PATTERN = Pattern.compile("(?i:host)=" + FORWARDED_VALUE); |
||||
|
||||
private static final Pattern FORWARDED_PROTO_PATTERN = Pattern.compile("(?i:proto)=" + FORWARDED_VALUE); |
||||
|
||||
private static final Pattern FORWARDED_FOR_PATTERN = Pattern.compile("(?i:for)=" + FORWARDED_VALUE); |
||||
|
||||
|
||||
/** |
||||
* 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 |
||||
* "X-Forwarded-Host", "X-Forwarded-Port", and "X-Forwarded-Proto" if "Forwarded" |
||||
* is not present. |
||||
* @param headers the HTTP headers to consider |
||||
* @return a {@link UriComponentsBuilder} that reflects the request URI and |
||||
* additional updates from forwarded headers |
||||
*/ |
||||
public static UriComponentsBuilder adaptFromForwardedHeaders(URI uri, HttpHeaders headers) { |
||||
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUri(uri); |
||||
try { |
||||
String forwardedHeader = headers.getFirst("Forwarded"); |
||||
if (StringUtils.hasText(forwardedHeader)) { |
||||
Matcher matcher = FORWARDED_PROTO_PATTERN.matcher(forwardedHeader); |
||||
if (matcher.find()) { |
||||
uriComponentsBuilder.scheme(matcher.group(1).trim()); |
||||
uriComponentsBuilder.port(null); |
||||
} |
||||
else if (isForwardedSslOn(headers)) { |
||||
uriComponentsBuilder.scheme("https"); |
||||
uriComponentsBuilder.port(null); |
||||
} |
||||
matcher = FORWARDED_HOST_PATTERN.matcher(forwardedHeader); |
||||
if (matcher.find()) { |
||||
adaptForwardedHost(uriComponentsBuilder, matcher.group(1).trim()); |
||||
} |
||||
} |
||||
else { |
||||
String protocolHeader = headers.getFirst("X-Forwarded-Proto"); |
||||
if (StringUtils.hasText(protocolHeader)) { |
||||
uriComponentsBuilder.scheme(StringUtils.tokenizeToStringArray(protocolHeader, ",")[0]); |
||||
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, StringUtils.tokenizeToStringArray(hostHeader, ",")[0]); |
||||
} |
||||
String portHeader = headers.getFirst("X-Forwarded-Port"); |
||||
if (StringUtils.hasText(portHeader)) { |
||||
uriComponentsBuilder.port(Integer.parseInt(StringUtils.tokenizeToStringArray(portHeader, ",")[0])); |
||||
} |
||||
} |
||||
} |
||||
catch (NumberFormatException ex) { |
||||
throw new IllegalArgumentException("Failed to parse a port from \"forwarded\"-type headers. " + |
||||
"If not behind a trusted proxy, consider using ForwardedHeaderFilter " + |
||||
"with the removeOnly=true. Request headers: " + headers); |
||||
} |
||||
|
||||
uriComponentsBuilder.resetPortIfDefaultForScheme(); |
||||
|
||||
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. |
||||
* @param uri the request URI |
||||
* @param headers the request headers that may contain forwarded headers |
||||
* @param remoteAddress the current remoteAddress |
||||
* @return an {@code InetSocketAddress} with the extracted host and port, or |
||||
* {@code null} if the headers are not present. |
||||
* @see <a href="https://tools.ietf.org/html/rfc7239#section-5.2">RFC 7239, Section 5.2</a> |
||||
*/ |
||||
@Nullable |
||||
public static 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]; |
||||
Matcher matcher = FORWARDED_FOR_PATTERN.matcher(forwardedToUse); |
||||
if (matcher.find()) { |
||||
String value = matcher.group(1).trim(); |
||||
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); |
||||
} |
||||
} |
||||
|
||||
String forHeader = headers.getFirst("X-Forwarded-For"); |
||||
if (StringUtils.hasText(forHeader)) { |
||||
String host = StringUtils.tokenizeToStringArray(forHeader, ",")[0]; |
||||
return InetSocketAddress.createUnresolved(host, port); |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,534 @@
@@ -0,0 +1,534 @@
|
||||
/* |
||||
* Copyright 2002-2023 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.web.util; |
||||
|
||||
import java.net.URI; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.params.ParameterizedTest; |
||||
import org.junit.jupiter.params.provider.ValueSource; |
||||
|
||||
import org.springframework.http.HttpHeaders; |
||||
import org.springframework.http.HttpMethod; |
||||
import org.springframework.http.HttpRequest; |
||||
import org.springframework.http.server.ServletServerHttpRequest; |
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; |
||||
|
||||
/** |
||||
* Unit tests for {@link UriComponentsBuilder}. |
||||
* |
||||
* @author Rossen Stoyanchev |
||||
*/ |
||||
class ForwardedHeaderUtilsTests { |
||||
|
||||
@Test |
||||
void fromHttpRequest() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(-1); |
||||
request.setRequestURI("/path"); |
||||
request.setQueryString("a=1"); |
||||
|
||||
ServletServerHttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
assertThat(result.getScheme()).isEqualTo("http"); |
||||
assertThat(result.getHost()).isEqualTo("localhost"); |
||||
assertThat(result.getPort()).isEqualTo(-1); |
||||
assertThat(result.getPath()).isEqualTo("/path"); |
||||
assertThat(result.getQuery()).isEqualTo("a=1"); |
||||
} |
||||
|
||||
@ParameterizedTest // gh-17368, gh-27097
|
||||
@ValueSource(strings = {"https", "wss"}) |
||||
void fromHttpRequestResetsPort443(String protocol) { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.addHeader("X-Forwarded-Proto", protocol); |
||||
request.addHeader("X-Forwarded-Host", "84.198.58.199"); |
||||
request.addHeader("X-Forwarded-Port", 443); |
||||
request.setScheme("http"); |
||||
request.setServerName("example.com"); |
||||
request.setServerPort(80); |
||||
request.setRequestURI("/rest/mobile/users/1"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getScheme()).isEqualTo(protocol); |
||||
assertThat(result.getHost()).isEqualTo("84.198.58.199"); |
||||
assertThat(result.getPort()).isEqualTo(-1); |
||||
assertThat(result.getPath()).isEqualTo("/rest/mobile/users/1"); |
||||
} |
||||
|
||||
@ParameterizedTest // gh-27097
|
||||
@ValueSource(strings = {"http", "ws"}) |
||||
void fromHttpRequestResetsPort80(String protocol) { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.addHeader("X-Forwarded-Proto", protocol); |
||||
request.addHeader("X-Forwarded-Host", "84.198.58.199"); |
||||
request.addHeader("X-Forwarded-Port", 80); |
||||
request.setScheme("http"); |
||||
request.setServerName("example.com"); |
||||
request.setServerPort(80); |
||||
request.setRequestURI("/path"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getScheme()).isEqualTo(protocol); |
||||
assertThat(result.getHost()).isEqualTo("84.198.58.199"); |
||||
assertThat(result.getPort()).isEqualTo(-1); |
||||
assertThat(result.getPath()).isEqualTo("/path"); |
||||
} |
||||
|
||||
@Test // SPR-14761
|
||||
void fromHttpRequestWithForwardedIPv4Host() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("https"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(-1); |
||||
request.setRequestURI("/mvc-showcase"); |
||||
request.addHeader("Forwarded", "host=192.168.0.1"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.toString()).isEqualTo("https://192.168.0.1/mvc-showcase"); |
||||
} |
||||
|
||||
@Test // SPR-14761
|
||||
void fromHttpRequestWithForwardedIPv6() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(-1); |
||||
request.setRequestURI("/mvc-showcase"); |
||||
request.addHeader("Forwarded", "host=[1abc:2abc:3abc::5ABC:6abc]"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.toString()).isEqualTo("http://[1abc:2abc:3abc::5ABC:6abc]/mvc-showcase"); |
||||
} |
||||
|
||||
@Test // SPR-14761
|
||||
void fromHttpRequestWithForwardedIPv6Host() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(-1); |
||||
request.setRequestURI("/mvc-showcase"); |
||||
request.addHeader("X-Forwarded-Host", "[1abc:2abc:3abc::5ABC:6abc]"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.toString()).isEqualTo("http://[1abc:2abc:3abc::5ABC:6abc]/mvc-showcase"); |
||||
} |
||||
|
||||
@Test // SPR-14761
|
||||
void fromHttpRequestWithForwardedIPv6HostAndPort() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(-1); |
||||
request.setRequestURI("/mvc-showcase"); |
||||
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(); |
||||
|
||||
assertThat(result.toString()).isEqualTo("http://[1abc:2abc:3abc::5ABC:6abc]:8080/mvc-showcase"); |
||||
} |
||||
|
||||
@Test // gh-26748
|
||||
void fromHttpRequestWithForwardedInvalidIPv6Address() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(-1); |
||||
request.setRequestURI("/mvc-showcase"); |
||||
request.addHeader("X-Forwarded-Host", "2a02:918:175:ab60:45ee:c12c:dac1:808b"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> |
||||
ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build()); |
||||
} |
||||
|
||||
@Test |
||||
void fromHttpRequestWithForwardedHost() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("https"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(-1); |
||||
request.setRequestURI("/mvc-showcase"); |
||||
request.addHeader("X-Forwarded-Host", "anotherHost"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.toString()).isEqualTo("https://anotherHost/mvc-showcase"); |
||||
} |
||||
|
||||
@Test // SPR-10701
|
||||
void fromHttpRequestWithForwardedHostIncludingPort() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(-1); |
||||
request.setRequestURI("/mvc-showcase"); |
||||
request.addHeader("X-Forwarded-Host", "webtest.foo.bar.com:443"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getHost()).isEqualTo("webtest.foo.bar.com"); |
||||
assertThat(result.getPort()).isEqualTo(443); |
||||
} |
||||
|
||||
@Test // SPR-11140
|
||||
void fromHttpRequestWithForwardedHostMultiValuedHeader() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(-1); |
||||
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(); |
||||
|
||||
assertThat(result.getHost()).isEqualTo("a.example.org"); |
||||
assertThat(result.getPort()).isEqualTo(-1); |
||||
} |
||||
|
||||
@Test // SPR-11855
|
||||
void fromHttpRequestWithForwardedHostAndPort() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(8080); |
||||
request.addHeader("X-Forwarded-Host", "foobarhost"); |
||||
request.addHeader("X-Forwarded-Port", "9090"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getHost()).isEqualTo("foobarhost"); |
||||
assertThat(result.getPort()).isEqualTo(9090); |
||||
} |
||||
|
||||
@Test // SPR-11872
|
||||
void fromHttpRequestWithForwardedHostWithDefaultPort() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(10080); |
||||
request.addHeader("X-Forwarded-Host", "example.org"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getHost()).isEqualTo("example.org"); |
||||
assertThat(result.getPort()).isEqualTo(-1); |
||||
} |
||||
|
||||
@Test // SPR-16262
|
||||
void fromHttpRequestWithForwardedProtoWithDefaultPort() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("example.org"); |
||||
request.setServerPort(10080); |
||||
request.addHeader("X-Forwarded-Proto", "https"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getScheme()).isEqualTo("https"); |
||||
assertThat(result.getHost()).isEqualTo("example.org"); |
||||
assertThat(result.getPort()).isEqualTo(-1); |
||||
} |
||||
|
||||
@Test // SPR-16863
|
||||
void fromHttpRequestWithForwardedSsl() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("example.org"); |
||||
request.setServerPort(10080); |
||||
request.addHeader("X-Forwarded-Ssl", "on"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getScheme()).isEqualTo("https"); |
||||
assertThat(result.getHost()).isEqualTo("example.org"); |
||||
assertThat(result.getPort()).isEqualTo(-1); |
||||
} |
||||
|
||||
@Test |
||||
void fromHttpRequestWithForwardedHostWithForwardedScheme() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(10080); |
||||
request.addHeader("X-Forwarded-Host", "example.org"); |
||||
request.addHeader("X-Forwarded-Proto", "https"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getHost()).isEqualTo("example.org"); |
||||
assertThat(result.getScheme()).isEqualTo("https"); |
||||
assertThat(result.getPort()).isEqualTo(-1); |
||||
} |
||||
|
||||
@Test // SPR-12771
|
||||
void fromHttpRequestWithForwardedProtoAndDefaultPort() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(80); |
||||
request.setRequestURI("/mvc-showcase"); |
||||
request.addHeader("X-Forwarded-Proto", "https"); |
||||
request.addHeader("X-Forwarded-Host", "84.198.58.199"); |
||||
request.addHeader("X-Forwarded-Port", "443"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.toString()).isEqualTo("https://84.198.58.199/mvc-showcase"); |
||||
} |
||||
|
||||
@Test // SPR-12813
|
||||
void fromHttpRequestWithForwardedPortMultiValueHeader() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(9090); |
||||
request.setRequestURI("/mvc-showcase"); |
||||
request.addHeader("X-Forwarded-Host", "a.example.org"); |
||||
request.addHeader("X-Forwarded-Port", "80,52022"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.toString()).isEqualTo("http://a.example.org/mvc-showcase"); |
||||
} |
||||
|
||||
@Test // SPR-12816
|
||||
void fromHttpRequestWithForwardedProtoMultiValueHeader() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.setScheme("http"); |
||||
request.setServerName("localhost"); |
||||
request.setServerPort(8080); |
||||
request.setRequestURI("/mvc-showcase"); |
||||
request.addHeader("X-Forwarded-Host", "a.example.org"); |
||||
request.addHeader("X-Forwarded-Port", "443"); |
||||
request.addHeader("X-Forwarded-Proto", "https,https"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.toString()).isEqualTo("https://a.example.org/mvc-showcase"); |
||||
} |
||||
|
||||
@Test // gh-19890
|
||||
void fromHttpRequestWithEmptyScheme() { |
||||
HttpRequest request = new HttpRequest() { |
||||
@Override |
||||
public HttpMethod getMethod() { |
||||
return HttpMethod.GET; |
||||
} |
||||
|
||||
@Override |
||||
public URI getURI() { |
||||
return UriComponentsBuilder.fromUriString("/").build().toUri(); |
||||
} |
||||
|
||||
@Override |
||||
public HttpHeaders getHeaders() { |
||||
return new HttpHeaders(); |
||||
} |
||||
}; |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(request.getURI(), request.getHeaders()).build(); |
||||
|
||||
assertThat(result.toString()).isEqualTo("/"); |
||||
} |
||||
|
||||
@Test // SPR-11856
|
||||
void fromHttpRequestForwardedHeader() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.addHeader("Forwarded", "proto=https; host=84.198.58.199"); |
||||
request.setScheme("http"); |
||||
request.setServerName("example.com"); |
||||
request.setRequestURI("/rest/mobile/users/1"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getScheme()).isEqualTo("https"); |
||||
assertThat(result.getHost()).isEqualTo("84.198.58.199"); |
||||
assertThat(result.getPath()).isEqualTo("/rest/mobile/users/1"); |
||||
} |
||||
|
||||
@Test |
||||
void fromHttpRequestForwardedHeaderQuoted() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.addHeader("Forwarded", "proto=\"https\"; host=\"84.198.58.199\""); |
||||
request.setScheme("http"); |
||||
request.setServerName("example.com"); |
||||
request.setRequestURI("/rest/mobile/users/1"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getScheme()).isEqualTo("https"); |
||||
assertThat(result.getHost()).isEqualTo("84.198.58.199"); |
||||
assertThat(result.getPath()).isEqualTo("/rest/mobile/users/1"); |
||||
} |
||||
|
||||
@Test |
||||
void fromHttpRequestMultipleForwardedHeader() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.addHeader("Forwarded", "host=84.198.58.199;proto=https"); |
||||
request.addHeader("Forwarded", "proto=ftp; host=1.2.3.4"); |
||||
request.setScheme("http"); |
||||
request.setServerName("example.com"); |
||||
request.setRequestURI("/rest/mobile/users/1"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getScheme()).isEqualTo("https"); |
||||
assertThat(result.getHost()).isEqualTo("84.198.58.199"); |
||||
assertThat(result.getPath()).isEqualTo("/rest/mobile/users/1"); |
||||
} |
||||
|
||||
@Test |
||||
void fromHttpRequestMultipleForwardedHeaderComma() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.addHeader("Forwarded", "host=84.198.58.199 ;proto=https, proto=ftp; host=1.2.3.4"); |
||||
request.setScheme("http"); |
||||
request.setServerName("example.com"); |
||||
request.setRequestURI("/rest/mobile/users/1"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getScheme()).isEqualTo("https"); |
||||
assertThat(result.getHost()).isEqualTo("84.198.58.199"); |
||||
assertThat(result.getPath()).isEqualTo("/rest/mobile/users/1"); |
||||
} |
||||
|
||||
@Test |
||||
void fromHttpRequestForwardedHeaderWithHostPortAndWithoutServerPort() { |
||||
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 = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getScheme()).isEqualTo("https"); |
||||
assertThat(result.getHost()).isEqualTo("84.198.58.199"); |
||||
assertThat(result.getPath()).isEqualTo("/rest/mobile/users/1"); |
||||
assertThat(result.getPort()).isEqualTo(9090); |
||||
assertThat(result.toUriString()).isEqualTo("https://84.198.58.199:9090/rest/mobile/users/1"); |
||||
} |
||||
|
||||
@Test |
||||
void fromHttpRequestForwardedHeaderWithHostPortAndServerPort() { |
||||
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 = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getScheme()).isEqualTo("https"); |
||||
assertThat(result.getHost()).isEqualTo("84.198.58.199"); |
||||
assertThat(result.getPath()).isEqualTo("/rest/mobile/users/1"); |
||||
assertThat(result.getPort()).isEqualTo(9090); |
||||
assertThat(result.toUriString()).isEqualTo("https://84.198.58.199:9090/rest/mobile/users/1"); |
||||
} |
||||
|
||||
@Test |
||||
void fromHttpRequestForwardedHeaderWithoutHostPortAndWithServerPort() { |
||||
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 = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getScheme()).isEqualTo("https"); |
||||
assertThat(result.getHost()).isEqualTo("84.198.58.199"); |
||||
assertThat(result.getPath()).isEqualTo("/rest/mobile/users/1"); |
||||
assertThat(result.getPort()).isEqualTo(-1); |
||||
assertThat(result.toUriString()).isEqualTo("https://84.198.58.199/rest/mobile/users/1"); |
||||
} |
||||
|
||||
@Test // SPR-16262
|
||||
void fromHttpRequestForwardedHeaderWithProtoAndServerPort() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.addHeader("Forwarded", "proto=https"); |
||||
request.setScheme("http"); |
||||
request.setServerPort(8080); |
||||
request.setServerName("example.com"); |
||||
request.setRequestURI("/rest/mobile/users/1"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getScheme()).isEqualTo("https"); |
||||
assertThat(result.getHost()).isEqualTo("example.com"); |
||||
assertThat(result.getPath()).isEqualTo("/rest/mobile/users/1"); |
||||
assertThat(result.getPort()).isEqualTo(-1); |
||||
assertThat(result.toUriString()).isEqualTo("https://example.com/rest/mobile/users/1"); |
||||
} |
||||
|
||||
@Test // gh-25737
|
||||
void fromHttpRequestForwardedHeaderComma() { |
||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
||||
request.addHeader("Forwarded", "for=192.0.2.0,for=192.0.2.1;proto=https;host=192.0.2.3:9090"); |
||||
request.setScheme("http"); |
||||
request.setServerPort(8080); |
||||
request.setServerName("example.com"); |
||||
request.setRequestURI("/rest/mobile/users/1"); |
||||
|
||||
HttpRequest httpRequest = new ServletServerHttpRequest(request); |
||||
UriComponents result = ForwardedHeaderUtils.adaptFromForwardedHeaders(httpRequest.getURI(), httpRequest.getHeaders()).build(); |
||||
|
||||
assertThat(result.getScheme()).isEqualTo("https"); |
||||
assertThat(result.getHost()).isEqualTo("192.0.2.3"); |
||||
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"); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue