Polish Forwarded header support

This commit is contained in:
Rossen Stoyanchev
2018-05-23 21:20:37 -04:00
parent 1e4a3a2370
commit 72022899de
4 changed files with 102 additions and 111 deletions

View File

@@ -42,19 +42,19 @@ import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UrlPathHelper;
/**
* Extract values from "Forwarded" and "X-Forwarded-*" headers in order to wrap
* and override the following from the request and response:
* {@link HttpServletRequest#getServerName() getServerName()},
* {@link HttpServletRequest#getServerPort() getServerPort()},
* {@link HttpServletRequest#getScheme() getScheme()},
* {@link HttpServletRequest#isSecure() isSecure()}, and
* {@link HttpServletResponse#sendRedirect(String) sendRedirect(String)}.
* In effect the wrapped request and response reflect the client-originated
* protocol and address.
* Extract values from "Forwarded" and "X-Forwarded-*" headers, wrap the request
* and response, and make they reflect the client-originated protocol and
* address in the following methods:
* <ul>
* <li>{@link HttpServletRequest#getServerName() getServerName()}
* <li>{@link HttpServletRequest#getServerPort() getServerPort()}
* <li>{@link HttpServletRequest#getScheme() getScheme()}
* <li>{@link HttpServletRequest#isSecure() isSecure()}
* <li>{@link HttpServletResponse#sendRedirect(String) sendRedirect(String)}.
* </ul>
*
* <p><strong>Note:</strong> This filter can also be used in a
* {@link #setRemoveOnly removeOnly} mode where "Forwarded" and "X-Forwarded-*"
* headers are only eliminated without being used.
* <p>This filter can also be used in a {@link #setRemoveOnly removeOnly} mode
* where "Forwarded" and "X-Forwarded-*" headers are eliminated, and not used.
*
* @author Rossen Stoyanchev
* @author Eddú Meléndez
@@ -117,7 +117,7 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
protected boolean shouldNotFilter(HttpServletRequest request) {
for (String headerName : FORWARDED_HEADER_NAMES) {
if (request.getHeader(headerName) != null) {
return false;
@@ -141,15 +141,18 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
FilterChain filterChain) throws ServletException, IOException {
if (this.removeOnly) {
ForwardedHeaderRemovingRequest theRequest = new ForwardedHeaderRemovingRequest(request);
filterChain.doFilter(theRequest, response);
ForwardedHeaderRemovingRequest wrappedRequest = new ForwardedHeaderRemovingRequest(request);
filterChain.doFilter(wrappedRequest, response);
}
else {
HttpServletRequest theRequest = new ForwardedHeaderExtractingRequest(request, this.pathHelper);
HttpServletResponse theResponse = (this.relativeRedirects ?
HttpServletRequest wrappedRequest =
new ForwardedHeaderExtractingRequest(request, this.pathHelper);
HttpServletResponse wrappedResponse = this.relativeRedirects ?
RelativeRedirectResponseWrapper.wrapIfNecessary(response, HttpStatus.SEE_OTHER) :
new ForwardedHeaderExtractingResponse(response, theRequest));
filterChain.doFilter(theRequest, theResponse);
new ForwardedHeaderExtractingResponse(response, wrappedRequest);
filterChain.doFilter(wrappedRequest, wrappedResponse);
}
}
@@ -221,7 +224,8 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
private final String requestUrl;
public ForwardedHeaderExtractingRequest(HttpServletRequest request, UrlPathHelper pathHelper) {
ForwardedHeaderExtractingRequest(HttpServletRequest request, UrlPathHelper pathHelper) {
super(request);
HttpRequest httpRequest = new ServletServerHttpRequest(request);
@@ -257,6 +261,7 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
return prefix;
}
@Override
@Nullable
public String getScheme() {
@@ -302,11 +307,13 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
private final HttpServletRequest request;
public ForwardedHeaderExtractingResponse(HttpServletResponse response, HttpServletRequest request) {
ForwardedHeaderExtractingResponse(HttpServletResponse response, HttpServletRequest request) {
super(response);
this.request = request;
}
@Override
public void sendRedirect(String location) throws IOException {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 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.
@@ -31,17 +31,16 @@ import org.springframework.web.server.WebFilterChain;
import org.springframework.web.util.UriComponentsBuilder;
/**
* Extract values from "Forwarded" and "X-Forwarded-*" headers in order to change
* and override {@link ServerHttpRequest#getURI()}.
* In effect the request URI will reflect the client-originated
* Extract values from "Forwarded" and "X-Forwarded-*" headers, and use them to
* override {@link ServerHttpRequest#getURI()} to reflect the client-originated
* protocol and address.
*
* <p><strong>Note:</strong> This filter can also be used in a
* {@link #setRemoveOnly removeOnly} mode where "Forwarded" and "X-Forwarded-*"
* headers are only eliminated without being used.
* <p>This filter can also be used in a {@link #setRemoveOnly removeOnly} mode
* where "Forwarded" and "X-Forwarded-*" headers are eliminated, and not used.
*
* @author Arjen Poutsma
* @see <a href="https://tools.ietf.org/html/rfc7239">https://tools.ietf.org/html/rfc7239</a>
* @since 5.0
* @see <a href="https://tools.ietf.org/html/rfc7239">https://tools.ietf.org/html/rfc7239</a>
*/
public class ForwardedHeaderFilter implements WebFilter {
@@ -55,8 +54,10 @@ public class ForwardedHeaderFilter implements WebFilter {
FORWARDED_HEADER_NAMES.add("X-Forwarded-Prefix");
}
private boolean removeOnly;
/**
* Enables mode in which any "Forwarded" or "X-Forwarded-*" headers are
* removed only and the information in them ignored.
@@ -66,6 +67,7 @@ public class ForwardedHeaderFilter implements WebFilter {
this.removeOnly = removeOnly;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
@@ -73,31 +75,29 @@ public class ForwardedHeaderFilter implements WebFilter {
return chain.filter(exchange);
}
ServerWebExchange mutatedExchange;
if (this.removeOnly) {
ServerWebExchange withoutForwardHeaders = exchange.mutate()
.request(builder -> builder.headers(
headers -> {
for (String headerName : FORWARDED_HEADER_NAMES) {
headers.remove(headerName);
}
})).build();
return chain.filter(withoutForwardHeaders);
mutatedExchange = exchange.mutate().request(builder ->
builder.headers(headers -> {
FORWARDED_HEADER_NAMES.forEach(headers::remove);
}))
.build();
}
else {
URI uri = UriComponentsBuilder.fromHttpRequest(exchange.getRequest()).build().toUri();
String prefix = getForwardedPrefix(exchange.getRequest().getHeaders());
ServerWebExchange withChangedUri = exchange.mutate()
.request(builder -> {
builder.uri(uri);
if (prefix != null) {
builder.path(prefix + uri.getPath());
builder.contextPath(prefix);
}
}).build();
return chain.filter(withChangedUri);
mutatedExchange = exchange.mutate().request(builder -> {
builder.uri(uri);
if (prefix != null) {
builder.path(prefix + uri.getPath());
builder.contextPath(prefix);
}
}).build();
}
return chain.filter(mutatedExchange);
}
private boolean shouldNotFilter(ServerHttpRequest request) {