Polish ForwardedHeaderFilter and related code
Issue: SPR-16506
This commit is contained in:
@@ -101,13 +101,13 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this property to enable relative redirects as explained in and also
|
||||
* using the same response wrapper as {@link RelativeRedirectFilter} does.
|
||||
* Or if both filters are used, only one will wrap the response.
|
||||
* Use this property to enable relative redirects as explained in
|
||||
* {@link RelativeRedirectFilter}, and also using the same response wrapper
|
||||
* as that filter does, or if both are configured, only one will wrap.
|
||||
* <p>By default, if this property is set to false, in which case calls to
|
||||
* {@link HttpServletResponse#sendRedirect(String)} are overridden in order
|
||||
* to turn relative into absolute URLs since (which Servlet containers are
|
||||
* also required to do) also taking forwarded headers into consideration.
|
||||
* to turn relative into absolute URLs, also taking into account forwarded
|
||||
* headers.
|
||||
* @param relativeRedirects whether to use relative redirects
|
||||
* @since 4.3.10
|
||||
*/
|
||||
@@ -307,54 +307,41 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRedirect(String location) throws IOException {
|
||||
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(location);
|
||||
@Override
|
||||
public void sendRedirect(String location) throws IOException {
|
||||
|
||||
// Absolute location
|
||||
if (builder.build().getScheme() != null) {
|
||||
super.sendRedirect(location);
|
||||
return;
|
||||
}
|
||||
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(location);
|
||||
UriComponents uriComponents = builder.build();
|
||||
|
||||
// Network-path reference
|
||||
if (location.startsWith("//")) {
|
||||
String scheme = this.request.getScheme();
|
||||
super.sendRedirect(builder.scheme(scheme).toUriString());
|
||||
return;
|
||||
}
|
||||
// Absolute location
|
||||
if (uriComponents.getScheme() != null) {
|
||||
super.sendRedirect(location);
|
||||
return;
|
||||
}
|
||||
|
||||
String fragment = null;
|
||||
int fragmentIndex = location.indexOf('#');
|
||||
if (fragmentIndex != -1) {
|
||||
if (location.length() > fragmentIndex) {
|
||||
fragment = location.substring(fragmentIndex + 1);
|
||||
}
|
||||
location = location.substring(0, fragmentIndex);
|
||||
}
|
||||
// Network-path reference
|
||||
if (location.startsWith("//")) {
|
||||
String scheme = this.request.getScheme();
|
||||
super.sendRedirect(builder.scheme(scheme).toUriString());
|
||||
return;
|
||||
}
|
||||
|
||||
String query = null;
|
||||
int queryIndex = location.indexOf('?');
|
||||
if (queryIndex != -1) {
|
||||
if (location.length() > queryIndex) {
|
||||
query = location.substring(queryIndex + 1);
|
||||
}
|
||||
location = location.substring(0, queryIndex);
|
||||
}
|
||||
String path = uriComponents.getPath();
|
||||
if (path != null) {
|
||||
// Relative to Servlet container root or to current request
|
||||
path = (path.startsWith(FOLDER_SEPARATOR) ? path :
|
||||
StringUtils.applyRelativePath(this.request.getRequestURI(), path));
|
||||
}
|
||||
|
||||
// Relative to Servlet container root or to current request
|
||||
String path = (location.startsWith(FOLDER_SEPARATOR) ? location :
|
||||
StringUtils.applyRelativePath(this.request.getRequestURI(), location));
|
||||
String result = UriComponentsBuilder
|
||||
.fromHttpRequest(new ServletServerHttpRequest(this.request))
|
||||
.replacePath(path)
|
||||
.replaceQuery(uriComponents.getQuery())
|
||||
.fragment(uriComponents.getFragment())
|
||||
.build().normalize().toUriString();
|
||||
|
||||
String result = UriComponentsBuilder
|
||||
.fromHttpRequest(new ServletServerHttpRequest(this.request))
|
||||
.replacePath(path)
|
||||
.replaceQuery(query)
|
||||
.fragment(fragment)
|
||||
.build().normalize().toUriString();
|
||||
|
||||
super.sendRedirect(result);
|
||||
}
|
||||
super.sendRedirect(result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -27,13 +27,14 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Overrides {@link HttpServletResponse#sendRedirect(String)} and handles it by
|
||||
* setting the HTTP status and "Location" headers. This keeps the Servlet
|
||||
* container from re-writing relative redirect URLs and instead follows the
|
||||
* recommendation in <a href="https://tools.ietf.org/html/rfc7231#section-7.1.2">
|
||||
* RFC 7231 Section 7.1.2</a>.
|
||||
* setting the HTTP status and "Location" headers, which keeps the Servlet
|
||||
* container from re-writing relative redirect URLs into absolute ones.
|
||||
* Servlet containers are required to do that but against the recommendation of
|
||||
* <a href="https://tools.ietf.org/html/rfc7231#section-7.1.2"> RFC 7231 Section 7.1.2</a>,
|
||||
* and furthermore not necessarily taking into account "X-Forwarded" headers.
|
||||
*
|
||||
* <p><strong>Note:</strong> While relative redirects are more efficient they
|
||||
* may not work with reverse proxies under some configurations.
|
||||
* <p><strong>Note:</strong> While relative redirects are recommended in the
|
||||
* RFC, under some configurations with reverse proxies they may not work.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Rossen Stoyanchev
|
||||
|
||||
@@ -15,14 +15,13 @@
|
||||
*/
|
||||
package org.springframework.web.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* A response wrapper used for the implementation of
|
||||
@@ -44,7 +43,7 @@ class RelativeRedirectResponseWrapper extends HttpServletResponseWrapper {
|
||||
|
||||
|
||||
@Override
|
||||
public void sendRedirect(String location) throws IOException {
|
||||
public void sendRedirect(String location) {
|
||||
setStatus(this.redirectStatus.value());
|
||||
setHeader(HttpHeaders.LOCATION, location);
|
||||
}
|
||||
@@ -53,20 +52,11 @@ class RelativeRedirectResponseWrapper extends HttpServletResponseWrapper {
|
||||
public static HttpServletResponse wrapIfNecessary(HttpServletResponse response,
|
||||
HttpStatus redirectStatus) {
|
||||
|
||||
return (hasWrapper(response) ? response : new RelativeRedirectResponseWrapper(response, redirectStatus));
|
||||
}
|
||||
RelativeRedirectResponseWrapper wrapper =
|
||||
WebUtils.getNativeResponse(response, RelativeRedirectResponseWrapper.class);
|
||||
|
||||
private static boolean hasWrapper(ServletResponse response) {
|
||||
if (response instanceof RelativeRedirectResponseWrapper) {
|
||||
return true;
|
||||
}
|
||||
while (response instanceof HttpServletResponseWrapper) {
|
||||
response = ((HttpServletResponseWrapper) response).getResponse();
|
||||
if (response instanceof RelativeRedirectResponseWrapper) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return (wrapper != null ? response :
|
||||
new RelativeRedirectResponseWrapper(response, redirectStatus));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user