Merge cf8032c62d
into b256babad5
This commit is contained in:
commit
8521008f99
|
@ -57,6 +57,8 @@ class DefaultServerHttpRequestBuilder implements ServerHttpRequest.Builder {
|
||||||
|
|
||||||
private @Nullable InetSocketAddress remoteAddress;
|
private @Nullable InetSocketAddress remoteAddress;
|
||||||
|
|
||||||
|
private @Nullable InetSocketAddress localAddress;
|
||||||
|
|
||||||
private final Flux<DataBuffer> body;
|
private final Flux<DataBuffer> body;
|
||||||
|
|
||||||
private final ServerHttpRequest originalRequest;
|
private final ServerHttpRequest originalRequest;
|
||||||
|
@ -131,10 +133,16 @@ class DefaultServerHttpRequestBuilder implements ServerHttpRequest.Builder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServerHttpRequest.Builder localAddress(InetSocketAddress localAddress) {
|
||||||
|
this.localAddress = localAddress;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServerHttpRequest build() {
|
public ServerHttpRequest build() {
|
||||||
return new MutatedServerHttpRequest(getUriToUse(), this.contextPath,
|
return new MutatedServerHttpRequest(getUriToUse(), this.contextPath,
|
||||||
this.httpMethod, this.sslInfo, this.remoteAddress, this.headers, this.body, this.originalRequest);
|
this.httpMethod, this.sslInfo, this.remoteAddress, this.localAddress, this.headers, this.body, this.originalRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
private URI getUriToUse() {
|
private URI getUriToUse() {
|
||||||
|
@ -182,16 +190,19 @@ class DefaultServerHttpRequestBuilder implements ServerHttpRequest.Builder {
|
||||||
|
|
||||||
private final @Nullable InetSocketAddress remoteAddress;
|
private final @Nullable InetSocketAddress remoteAddress;
|
||||||
|
|
||||||
|
private final @Nullable InetSocketAddress localAddress;
|
||||||
|
|
||||||
private final Flux<DataBuffer> body;
|
private final Flux<DataBuffer> body;
|
||||||
|
|
||||||
private final ServerHttpRequest originalRequest;
|
private final ServerHttpRequest originalRequest;
|
||||||
|
|
||||||
public MutatedServerHttpRequest(URI uri, @Nullable String contextPath,
|
public MutatedServerHttpRequest(URI uri, @Nullable String contextPath,
|
||||||
HttpMethod method, @Nullable SslInfo sslInfo, @Nullable InetSocketAddress remoteAddress,
|
HttpMethod method, @Nullable SslInfo sslInfo, @Nullable InetSocketAddress remoteAddress, @Nullable InetSocketAddress localAddress,
|
||||||
HttpHeaders headers, Flux<DataBuffer> body, ServerHttpRequest originalRequest) {
|
HttpHeaders headers, Flux<DataBuffer> body, ServerHttpRequest originalRequest) {
|
||||||
|
|
||||||
super(method, uri, contextPath, headers);
|
super(method, uri, contextPath, headers);
|
||||||
this.remoteAddress = (remoteAddress != null ? remoteAddress : originalRequest.getRemoteAddress());
|
this.remoteAddress = (remoteAddress != null ? remoteAddress : originalRequest.getRemoteAddress());
|
||||||
|
this.localAddress = (localAddress != null ? localAddress : originalRequest.getLocalAddress());
|
||||||
this.sslInfo = (sslInfo != null ? sslInfo : originalRequest.getSslInfo());
|
this.sslInfo = (sslInfo != null ? sslInfo : originalRequest.getSslInfo());
|
||||||
this.body = body;
|
this.body = body;
|
||||||
this.originalRequest = originalRequest;
|
this.originalRequest = originalRequest;
|
||||||
|
@ -204,7 +215,7 @@ class DefaultServerHttpRequestBuilder implements ServerHttpRequest.Builder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable InetSocketAddress getLocalAddress() {
|
public @Nullable InetSocketAddress getLocalAddress() {
|
||||||
return this.originalRequest.getLocalAddress();
|
return this.localAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -184,6 +184,12 @@ public interface ServerHttpRequest extends HttpRequest, ReactiveHttpInputMessage
|
||||||
*/
|
*/
|
||||||
Builder remoteAddress(InetSocketAddress remoteAddress);
|
Builder remoteAddress(InetSocketAddress remoteAddress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the address of the local client.
|
||||||
|
* @since 7.x
|
||||||
|
*/
|
||||||
|
Builder localAddress(InetSocketAddress localAddress);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a {@link ServerHttpRequest} decorator with the mutated properties.
|
* Build a {@link ServerHttpRequest} decorator with the mutated properties.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -73,6 +73,7 @@ import org.springframework.web.util.WebUtils;
|
||||||
* @author Eddú Meléndez
|
* @author Eddú Meléndez
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
|
* @author Mengqi Xu
|
||||||
* @since 4.3
|
* @since 4.3
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc7239">https://tools.ietf.org/html/rfc7239</a>
|
* @see <a href="https://tools.ietf.org/html/rfc7239">https://tools.ietf.org/html/rfc7239</a>
|
||||||
* @see <a href="https://docs.spring.io/spring-framework/reference/web/webmvc/filters.html#filters-forwarded-headers">Forwarded Headers</a>
|
* @see <a href="https://docs.spring.io/spring-framework/reference/web/webmvc/filters.html#filters-forwarded-headers">Forwarded Headers</a>
|
||||||
|
@ -92,6 +93,7 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
|
||||||
FORWARDED_HEADER_NAMES.add("X-Forwarded-Prefix");
|
FORWARDED_HEADER_NAMES.add("X-Forwarded-Prefix");
|
||||||
FORWARDED_HEADER_NAMES.add("X-Forwarded-Ssl");
|
FORWARDED_HEADER_NAMES.add("X-Forwarded-Ssl");
|
||||||
FORWARDED_HEADER_NAMES.add("X-Forwarded-For");
|
FORWARDED_HEADER_NAMES.add("X-Forwarded-For");
|
||||||
|
FORWARDED_HEADER_NAMES.add("X-Forwarded-By");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -255,6 +257,8 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
private final @Nullable InetSocketAddress remoteAddress;
|
private final @Nullable InetSocketAddress remoteAddress;
|
||||||
|
|
||||||
|
private final @Nullable InetSocketAddress localAddress;
|
||||||
|
|
||||||
private final ForwardedPrefixExtractor forwardedPrefixExtractor;
|
private final ForwardedPrefixExtractor forwardedPrefixExtractor;
|
||||||
|
|
||||||
ForwardedHeaderExtractingRequest(HttpServletRequest servletRequest) {
|
ForwardedHeaderExtractingRequest(HttpServletRequest servletRequest) {
|
||||||
|
@ -272,6 +276,7 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
|
||||||
this.port = (port == -1 ? (this.secure ? 443 : 80) : port);
|
this.port = (port == -1 ? (this.secure ? 443 : 80) : port);
|
||||||
|
|
||||||
this.remoteAddress = ForwardedHeaderUtils.parseForwardedFor(uri, headers, request.getRemoteAddress());
|
this.remoteAddress = ForwardedHeaderUtils.parseForwardedFor(uri, headers, request.getRemoteAddress());
|
||||||
|
this.localAddress = ForwardedHeaderUtils.parseForwardedBy(uri, headers, request.getLocalAddress());
|
||||||
|
|
||||||
// Use Supplier as Tomcat updates delegate request on FORWARD
|
// Use Supplier as Tomcat updates delegate request on FORWARD
|
||||||
Supplier<HttpServletRequest> requestSupplier = () -> (HttpServletRequest) getRequest();
|
Supplier<HttpServletRequest> requestSupplier = () -> (HttpServletRequest) getRequest();
|
||||||
|
@ -330,6 +335,16 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
|
||||||
return (this.remoteAddress != null ? this.remoteAddress.getPort() : super.getRemotePort());
|
return (this.remoteAddress != null ? this.remoteAddress.getPort() : super.getRemotePort());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable String getLocalAddr() {
|
||||||
|
return (this.localAddress != null ? this.localAddress.getHostString() : super.getLocalAddr());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLocalPort() {
|
||||||
|
return (this.localAddress != null ? this.localAddress.getPort() : super.getLocalPort());
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("DataFlowIssue")
|
@SuppressWarnings("DataFlowIssue")
|
||||||
@Override
|
@Override
|
||||||
public @Nullable Object getAttribute(String name) {
|
public @Nullable Object getAttribute(String name) {
|
||||||
|
|
|
@ -55,6 +55,7 @@ import org.springframework.web.util.UriComponents;
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @author Sebastien Deleuze
|
* @author Sebastien Deleuze
|
||||||
|
* @author Mengqi Xu
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc7239">https://tools.ietf.org/html/rfc7239</a>
|
* @see <a href="https://tools.ietf.org/html/rfc7239">https://tools.ietf.org/html/rfc7239</a>
|
||||||
* @see <a href="https://docs.spring.io/spring-framework/reference/web/webflux/reactive-spring.html#webflux-forwarded-headers">Forwarded Headers</a>
|
* @see <a href="https://docs.spring.io/spring-framework/reference/web/webflux/reactive-spring.html#webflux-forwarded-headers">Forwarded Headers</a>
|
||||||
|
@ -72,6 +73,7 @@ public class ForwardedHeaderTransformer implements Function<ServerHttpRequest, S
|
||||||
FORWARDED_HEADER_NAMES.add("X-Forwarded-Prefix");
|
FORWARDED_HEADER_NAMES.add("X-Forwarded-Prefix");
|
||||||
FORWARDED_HEADER_NAMES.add("X-Forwarded-Ssl");
|
FORWARDED_HEADER_NAMES.add("X-Forwarded-Ssl");
|
||||||
FORWARDED_HEADER_NAMES.add("X-Forwarded-For");
|
FORWARDED_HEADER_NAMES.add("X-Forwarded-For");
|
||||||
|
FORWARDED_HEADER_NAMES.add("X-Forwarded-By");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -119,6 +121,11 @@ public class ForwardedHeaderTransformer implements Function<ServerHttpRequest, S
|
||||||
if (remoteAddress != null) {
|
if (remoteAddress != null) {
|
||||||
builder.remoteAddress(remoteAddress);
|
builder.remoteAddress(remoteAddress);
|
||||||
}
|
}
|
||||||
|
InetSocketAddress localAddress = request.getLocalAddress();
|
||||||
|
localAddress = ForwardedHeaderUtils.parseForwardedBy(originalUri, headers, localAddress);
|
||||||
|
if (localAddress != null) {
|
||||||
|
builder.localAddress(localAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
removeForwardedHeaders(builder);
|
removeForwardedHeaders(builder);
|
||||||
request = builder.build();
|
request = builder.build();
|
||||||
|
|
|
@ -54,6 +54,7 @@ public abstract class ForwardedHeaderUtils {
|
||||||
|
|
||||||
private static final Pattern FORWARDED_FOR_PATTERN = Pattern.compile("(?i:for)=" + FORWARDED_VALUE);
|
private static final Pattern FORWARDED_FOR_PATTERN = Pattern.compile("(?i:for)=" + FORWARDED_VALUE);
|
||||||
|
|
||||||
|
private static final Pattern FORWARDED_BY_PATTERN = Pattern.compile("(?i:by)=" + FORWARDED_VALUE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapt the scheme+host+port of the given {@link URI} from the "Forwarded" header
|
* Adapt the scheme+host+port of the given {@link URI} from the "Forwarded" header
|
||||||
|
@ -189,4 +190,57 @@ public abstract class ForwardedHeaderUtils {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the first "Forwarded: by=..." or "X-Forwarded-By" header value to
|
||||||
|
* an {@code InetSocketAddress} representing the address of the server.
|
||||||
|
* @param uri the request {@code URI}
|
||||||
|
* @param headers the request headers that may contain forwarded headers
|
||||||
|
* @param localAddress the current local address
|
||||||
|
* @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.1">RFC 7239, Section 5.1</a>
|
||||||
|
*/
|
||||||
|
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];
|
||||||
|
Matcher matcher = FORWARDED_BY_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 byHeader = headers.getFirst("X-Forwarded-By");
|
||||||
|
if (StringUtils.hasText(byHeader)) {
|
||||||
|
String host = StringUtils.tokenizeToStringArray(byHeader, ",")[0];
|
||||||
|
boolean ipv6 = (host.indexOf(':') != -1);
|
||||||
|
host = (ipv6 && !host.startsWith("[") && !host.endsWith("]") ? "[" + host + "]" : host);
|
||||||
|
return InetSocketAddress.createUnresolved(host, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ import static org.mockito.Mockito.mock;
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
* @author Sebastien Deleuze
|
* @author Sebastien Deleuze
|
||||||
|
* @author Mengqi Xu
|
||||||
*/
|
*/
|
||||||
class ForwardedHeaderFilterTests {
|
class ForwardedHeaderFilterTests {
|
||||||
|
|
||||||
|
@ -66,6 +67,8 @@ class ForwardedHeaderFilterTests {
|
||||||
|
|
||||||
private static final String X_FORWARDED_FOR = "x-forwarded-for";
|
private static final String X_FORWARDED_FOR = "x-forwarded-for";
|
||||||
|
|
||||||
|
private static final String X_FORWARDED_BY = "x-forwarded-by";
|
||||||
|
|
||||||
|
|
||||||
private final ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
|
private final ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
|
||||||
|
|
||||||
|
@ -93,6 +96,7 @@ class ForwardedHeaderFilterTests {
|
||||||
testShouldFilter(X_FORWARDED_SSL);
|
testShouldFilter(X_FORWARDED_SSL);
|
||||||
testShouldFilter(X_FORWARDED_PREFIX);
|
testShouldFilter(X_FORWARDED_PREFIX);
|
||||||
testShouldFilter(X_FORWARDED_FOR);
|
testShouldFilter(X_FORWARDED_FOR);
|
||||||
|
testShouldFilter(X_FORWARDED_BY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testShouldFilter(String headerName) {
|
private void testShouldFilter(String headerName) {
|
||||||
|
@ -115,6 +119,7 @@ class ForwardedHeaderFilterTests {
|
||||||
this.request.addHeader(X_FORWARDED_PORT, "443");
|
this.request.addHeader(X_FORWARDED_PORT, "443");
|
||||||
this.request.addHeader("foo", "bar");
|
this.request.addHeader("foo", "bar");
|
||||||
this.request.addHeader(X_FORWARDED_FOR, "[203.0.113.195]");
|
this.request.addHeader(X_FORWARDED_FOR, "[203.0.113.195]");
|
||||||
|
this.request.addHeader(X_FORWARDED_BY, "[203.0.113.196]");
|
||||||
|
|
||||||
this.filter.doFilter(this.request, new MockHttpServletResponse(), this.filterChain);
|
this.filter.doFilter(this.request, new MockHttpServletResponse(), this.filterChain);
|
||||||
HttpServletRequest actual = (HttpServletRequest) this.filterChain.getRequest();
|
HttpServletRequest actual = (HttpServletRequest) this.filterChain.getRequest();
|
||||||
|
@ -126,11 +131,13 @@ class ForwardedHeaderFilterTests {
|
||||||
assertThat(actual.getServerPort()).isEqualTo(443);
|
assertThat(actual.getServerPort()).isEqualTo(443);
|
||||||
assertThat(actual.isSecure()).isTrue();
|
assertThat(actual.isSecure()).isTrue();
|
||||||
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("[203.0.113.195]");
|
assertThat(actual.getRemoteAddr()).isEqualTo(actual.getRemoteHost()).isEqualTo("[203.0.113.195]");
|
||||||
|
assertThat(actual.getLocalAddr()).isEqualTo(actual.getLocalAddr()).isEqualTo("[203.0.113.196]");
|
||||||
|
|
||||||
assertThat(actual.getHeader(X_FORWARDED_PROTO)).isNull();
|
assertThat(actual.getHeader(X_FORWARDED_PROTO)).isNull();
|
||||||
assertThat(actual.getHeader(X_FORWARDED_HOST)).isNull();
|
assertThat(actual.getHeader(X_FORWARDED_HOST)).isNull();
|
||||||
assertThat(actual.getHeader(X_FORWARDED_PORT)).isNull();
|
assertThat(actual.getHeader(X_FORWARDED_PORT)).isNull();
|
||||||
assertThat(actual.getHeader(X_FORWARDED_FOR)).isNull();
|
assertThat(actual.getHeader(X_FORWARDED_FOR)).isNull();
|
||||||
|
assertThat(actual.getHeader(X_FORWARDED_BY)).isNull();
|
||||||
assertThat(actual.getHeader("foo")).isEqualTo("bar");
|
assertThat(actual.getHeader("foo")).isEqualTo("bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,6 +150,7 @@ class ForwardedHeaderFilterTests {
|
||||||
this.request.addHeader(X_FORWARDED_SSL, "on");
|
this.request.addHeader(X_FORWARDED_SSL, "on");
|
||||||
this.request.addHeader("foo", "bar");
|
this.request.addHeader("foo", "bar");
|
||||||
this.request.addHeader(X_FORWARDED_FOR, "203.0.113.195");
|
this.request.addHeader(X_FORWARDED_FOR, "203.0.113.195");
|
||||||
|
this.request.addHeader(X_FORWARDED_BY, "203.0.113.196");
|
||||||
|
|
||||||
this.filter.setRemoveOnly(true);
|
this.filter.setRemoveOnly(true);
|
||||||
this.filter.doFilter(this.request, new MockHttpServletResponse(), this.filterChain);
|
this.filter.doFilter(this.request, new MockHttpServletResponse(), this.filterChain);
|
||||||
|
@ -156,12 +164,14 @@ class ForwardedHeaderFilterTests {
|
||||||
assertThat(actual.isSecure()).isFalse();
|
assertThat(actual.isSecure()).isFalse();
|
||||||
assertThat(actual.getRemoteAddr()).isEqualTo(MockHttpServletRequest.DEFAULT_REMOTE_ADDR);
|
assertThat(actual.getRemoteAddr()).isEqualTo(MockHttpServletRequest.DEFAULT_REMOTE_ADDR);
|
||||||
assertThat(actual.getRemoteHost()).isEqualTo(MockHttpServletRequest.DEFAULT_REMOTE_HOST);
|
assertThat(actual.getRemoteHost()).isEqualTo(MockHttpServletRequest.DEFAULT_REMOTE_HOST);
|
||||||
|
assertThat(actual.getLocalAddr()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_ADDR);
|
||||||
|
|
||||||
assertThat(actual.getHeader(X_FORWARDED_PROTO)).isNull();
|
assertThat(actual.getHeader(X_FORWARDED_PROTO)).isNull();
|
||||||
assertThat(actual.getHeader(X_FORWARDED_HOST)).isNull();
|
assertThat(actual.getHeader(X_FORWARDED_HOST)).isNull();
|
||||||
assertThat(actual.getHeader(X_FORWARDED_PORT)).isNull();
|
assertThat(actual.getHeader(X_FORWARDED_PORT)).isNull();
|
||||||
assertThat(actual.getHeader(X_FORWARDED_SSL)).isNull();
|
assertThat(actual.getHeader(X_FORWARDED_SSL)).isNull();
|
||||||
assertThat(actual.getHeader(X_FORWARDED_FOR)).isNull();
|
assertThat(actual.getHeader(X_FORWARDED_FOR)).isNull();
|
||||||
|
assertThat(actual.getHeader(X_FORWARDED_BY)).isNull();
|
||||||
assertThat(actual.getHeader("foo")).isEqualTo("bar");
|
assertThat(actual.getHeader("foo")).isEqualTo("bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,6 +551,83 @@ class ForwardedHeaderFilterTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class ForwardedBy {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void xForwardedForEmpty() throws Exception {
|
||||||
|
request.addHeader(X_FORWARDED_BY, "");
|
||||||
|
HttpServletRequest actual = filterAndGetWrappedRequest();
|
||||||
|
|
||||||
|
assertThat(actual.getLocalAddr()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_ADDR);
|
||||||
|
assertThat(actual.getLocalPort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void xForwardedForSingleIdentifier() throws Exception {
|
||||||
|
request.addHeader(X_FORWARDED_BY, "203.0.113.195");
|
||||||
|
HttpServletRequest actual = filterAndGetWrappedRequest();
|
||||||
|
|
||||||
|
assertThat(actual.getLocalAddr()).isEqualTo(actual.getLocalAddr()).isEqualTo("203.0.113.195");
|
||||||
|
assertThat(actual.getLocalPort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void xForwardedForMultipleIdentifiers() throws Exception {
|
||||||
|
request.addHeader(X_FORWARDED_BY, "203.0.113.195, 70.41.3.18, 150.172.238.178");
|
||||||
|
HttpServletRequest actual = filterAndGetWrappedRequest();
|
||||||
|
|
||||||
|
assertThat(actual.getLocalAddr()).isEqualTo(actual.getLocalAddr()).isEqualTo("203.0.113.195");
|
||||||
|
assertThat(actual.getLocalPort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void forwardedForIpV4Identifier() throws Exception {
|
||||||
|
request.addHeader(FORWARDED, "By=203.0.113.195");
|
||||||
|
HttpServletRequest actual = filterAndGetWrappedRequest();
|
||||||
|
|
||||||
|
assertThat(actual.getLocalAddr()).isEqualTo(actual.getLocalAddr()).isEqualTo("203.0.113.195");
|
||||||
|
assertThat(actual.getLocalPort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void forwardedForIpV6Identifier() throws Exception {
|
||||||
|
request.addHeader(FORWARDED, "By=\"[2001:db8:cafe::17]\"");
|
||||||
|
HttpServletRequest actual = filterAndGetWrappedRequest();
|
||||||
|
|
||||||
|
assertThat(actual.getLocalAddr()).isEqualTo(actual.getLocalAddr()).isEqualTo("[2001:db8:cafe::17]");
|
||||||
|
assertThat(actual.getLocalPort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void forwardedForIpV4IdentifierWithPort() throws Exception {
|
||||||
|
request.addHeader(FORWARDED, "By=\"203.0.113.195:47011\"");
|
||||||
|
HttpServletRequest actual = filterAndGetWrappedRequest();
|
||||||
|
|
||||||
|
assertThat(actual.getLocalAddr()).isEqualTo(actual.getLocalAddr()).isEqualTo("203.0.113.195");
|
||||||
|
assertThat(actual.getLocalPort()).isEqualTo(47011);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void forwardedForIpV6IdentifierWithPort() throws Exception {
|
||||||
|
request.addHeader(FORWARDED, "By=\"[2001:db8:cafe::17]:47011\"");
|
||||||
|
HttpServletRequest actual = filterAndGetWrappedRequest();
|
||||||
|
|
||||||
|
assertThat(actual.getLocalAddr()).isEqualTo(actual.getLocalAddr()).isEqualTo("[2001:db8:cafe::17]");
|
||||||
|
assertThat(actual.getLocalPort()).isEqualTo(47011);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void forwardedForMultipleIdentifiers() throws Exception {
|
||||||
|
request.addHeader(FORWARDED, "by=203.0.113.195;proto=http, by=\"[2001:db8:cafe::17]\", by=unknown");
|
||||||
|
HttpServletRequest actual = filterAndGetWrappedRequest();
|
||||||
|
|
||||||
|
assertThat(actual.getLocalAddr()).isEqualTo(actual.getLocalAddr()).isEqualTo("203.0.113.195");
|
||||||
|
assertThat(actual.getLocalPort()).isEqualTo(MockHttpServletRequest.DEFAULT_SERVER_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class SendRedirect {
|
class SendRedirect {
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @author Sebastien Deleuze
|
* @author Sebastien Deleuze
|
||||||
|
* @author Mengqi Xu
|
||||||
*/
|
*/
|
||||||
class ForwardedHeaderTransformerTests {
|
class ForwardedHeaderTransformerTests {
|
||||||
|
|
||||||
|
@ -52,6 +53,7 @@ class ForwardedHeaderTransformerTests {
|
||||||
headers.add("X-Forwarded-Prefix", "prefix");
|
headers.add("X-Forwarded-Prefix", "prefix");
|
||||||
headers.add("X-Forwarded-Ssl", "on");
|
headers.add("X-Forwarded-Ssl", "on");
|
||||||
headers.add("X-Forwarded-For", "203.0.113.195");
|
headers.add("X-Forwarded-For", "203.0.113.195");
|
||||||
|
headers.add("X-Forwarded-By", "203.0.113.196");
|
||||||
ServerHttpRequest request = this.requestMutator.apply(getRequest(headers));
|
ServerHttpRequest request = this.requestMutator.apply(getRequest(headers));
|
||||||
|
|
||||||
assertForwardedHeadersRemoved(request);
|
assertForwardedHeadersRemoved(request);
|
||||||
|
@ -233,6 +235,40 @@ class ForwardedHeaderTransformerTests {
|
||||||
assertThat(request.getRemoteAddress().getHostName()).isEqualTo("203.0.113.195");
|
assertThat(request.getRemoteAddress().getHostName()).isEqualTo("203.0.113.195");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void forwardedBy() {
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.add("Forwarded", "by=\"203.0.113.195:4711\";host=84.198.58.199;proto=https");
|
||||||
|
|
||||||
|
InetSocketAddress localAddress = new InetSocketAddress("example.client", 47011);
|
||||||
|
|
||||||
|
ServerHttpRequest request = MockServerHttpRequest
|
||||||
|
.method(HttpMethod.GET, URI.create("https://example.com/a%20b?q=a%2Bb"))
|
||||||
|
.localAddress(localAddress)
|
||||||
|
.headers(headers)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
request = this.requestMutator.apply(request);
|
||||||
|
assertThat(request.getLocalAddress()).isNotNull();
|
||||||
|
assertThat(request.getLocalAddress().getHostName()).isEqualTo("203.0.113.195");
|
||||||
|
assertThat(request.getLocalAddress().getPort()).isEqualTo(4711);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void xForwardedBy() {
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.add("x-forwarded-by", "203.0.113.195, 70.41.3.18, 150.172.238.178");
|
||||||
|
|
||||||
|
ServerHttpRequest request = MockServerHttpRequest
|
||||||
|
.method(HttpMethod.GET, URI.create("https://example.com/a%20b?q=a%2Bb"))
|
||||||
|
.headers(headers)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
request = this.requestMutator.apply(request);
|
||||||
|
assertThat(request.getLocalAddress()).isNotNull();
|
||||||
|
assertThat(request.getLocalAddress().getHostName()).isEqualTo("203.0.113.195");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private MockServerHttpRequest getRequest(HttpHeaders headers) {
|
private MockServerHttpRequest getRequest(HttpHeaders headers) {
|
||||||
return MockServerHttpRequest.get(BASE_URL).headers(headers).build();
|
return MockServerHttpRequest.get(BASE_URL).headers(headers).build();
|
||||||
|
|
Loading…
Reference in New Issue