#758 - Centralize all Forward header handling.
Spring 5.1 is centralizing all Forward header handling. This moves critical bits into one location, making it easy to completely remove once we rebaseline against this version. Also adds a test profile to ensure Spring 5.1 doesn't break anything. Original pull request: #717.
This commit is contained in:
committed by
Oliver Drotbohm
parent
267ff45043
commit
bb4a4a615c
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.hateoas.mvc;
|
||||
|
||||
import static org.springframework.util.StringUtils.*;
|
||||
import static org.springframework.hateoas.mvc.ForwardedHeader.handleXForwardedSslHeader;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.Delegate;
|
||||
@@ -28,6 +28,7 @@ import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.hateoas.Affordance;
|
||||
import org.springframework.hateoas.Link;
|
||||
@@ -306,27 +307,37 @@ public class ControllerLinkBuilder extends LinkBuilderSupport<ControllerLinkBuil
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static UriComponentsBuilder getBuilder() {
|
||||
public static UriComponentsBuilder getBuilder() {
|
||||
|
||||
if (RequestContextHolder.getRequestAttributes() == null) {
|
||||
return UriComponentsBuilder.fromPath("/");
|
||||
}
|
||||
|
||||
HttpServletRequest request = getCurrentRequest();
|
||||
UriComponentsBuilder builder = ServletUriComponentsBuilder.fromServletMapping(request);
|
||||
ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromServletMapping(request);
|
||||
|
||||
// special case handling for X-Forwarded-Ssl:
|
||||
// apply it, but only if X-Forwarded-Proto is unset.
|
||||
|
||||
String forwardedSsl = request.getHeader("X-Forwarded-Ssl");
|
||||
ForwardedHeader forwarded = ForwardedHeader.of(request.getHeader(ForwardedHeader.NAME));
|
||||
String proto = hasText(forwarded.getProto()) ? forwarded.getProto() : request.getHeader("X-Forwarded-Proto");
|
||||
|
||||
if (!hasText(proto) && hasText(forwardedSsl) && forwardedSsl.equalsIgnoreCase("on")) {
|
||||
builder.scheme("https");
|
||||
// Spring 5.1 can handle X-Forwarded-Ssl headers...
|
||||
if (isSpringAtLeast5_1()) {
|
||||
return builder;
|
||||
} else {
|
||||
return handleXForwardedSslHeader(request, builder);
|
||||
}
|
||||
}
|
||||
|
||||
return builder;
|
||||
/**
|
||||
* Check if the current version of Spring Framework is 5.1 or higher.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static boolean isSpringAtLeast5_1() {
|
||||
|
||||
String versionOfSpringFramework = ApplicationContext.class.getPackage().getImplementationVersion();
|
||||
|
||||
String[] parts = versionOfSpringFramework.split("\\.");
|
||||
int majorVersion = Integer.parseInt(parts[0]);
|
||||
int minorVersion = Integer.parseInt(parts[1]);
|
||||
|
||||
return (majorVersion >= 5 && minorVersion >= 1) || (majorVersion > 5);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -361,13 +372,13 @@ public class ControllerLinkBuilder extends LinkBuilderSupport<ControllerLinkBuil
|
||||
private static class CachingAnnotationMappingDiscoverer implements MappingDiscoverer {
|
||||
|
||||
private final @Delegate AnnotationMappingDiscoverer delegate;
|
||||
private final Map<String, UriTemplate> templates = new ConcurrentReferenceHashMap<>();
|
||||
private final Map<String, UriTemplate> templates = new ConcurrentReferenceHashMap<>();
|
||||
|
||||
public UriTemplate getMappingAsUriTemplate(Class<?> type, Method method) {
|
||||
|
||||
String mapping = delegate.getMapping(type, method);
|
||||
|
||||
return templates.computeIfAbsent(mapping, UriTemplate::new);
|
||||
|
||||
return templates.computeIfAbsent(mapping, UriTemplate::new);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,38 +15,70 @@
|
||||
*/
|
||||
package org.springframework.hateoas.mvc;
|
||||
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Value object to partially implement the {@literal Forwarded} header defined in RFC 7239.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @see http://tools.ietf.org/html/rfc7239
|
||||
* @deprecated In Spring 5.1, all Forwarded headers will by handled by Spring MVC.
|
||||
*/
|
||||
@Deprecated
|
||||
class ForwardedHeader {
|
||||
|
||||
public static String NAME = "Forwarded";
|
||||
private static final ForwardedHeader NO_HEADER = new ForwardedHeader(Collections.emptyMap());
|
||||
|
||||
private final Map<String, String> elements;
|
||||
|
||||
private ForwardedHeader(Map<String, String> elements) {
|
||||
this.elements = elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to pull handling of {@literal X-Forwarded-Ssl} into a class that will be removed when
|
||||
* rebaselined against Spring 5.1
|
||||
*
|
||||
* @param request
|
||||
* @param builder
|
||||
* @return
|
||||
* @deprecated No longer needed with Spring 5.1
|
||||
*/
|
||||
@Deprecated
|
||||
public static UriComponentsBuilder handleXForwardedSslHeader(HttpServletRequest request, UriComponentsBuilder builder) {
|
||||
|
||||
// special case handling for X-Forwarded-Ssl:
|
||||
// apply it, but only if X-Forwarded-Proto is unset.
|
||||
|
||||
String forwardedSsl = request.getHeader("X-Forwarded-Ssl");
|
||||
ForwardedHeader forwarded = ForwardedHeader.of(request.getHeader("Forwarded"));
|
||||
String proto = hasText(forwarded.getProto()) ? forwarded.getProto() : request.getHeader("X-Forwarded-Proto");
|
||||
|
||||
if (!hasText(proto) && hasText(forwardedSsl) && forwardedSsl.equalsIgnoreCase("on")) {
|
||||
builder.scheme("https");
|
||||
}
|
||||
|
||||
return builder;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ForwardedHeader} from the given source.
|
||||
*
|
||||
* @param source can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static ForwardedHeader of(String source) {
|
||||
static ForwardedHeader of(String source) {
|
||||
|
||||
if (!StringUtils.hasText(source)) {
|
||||
return NO_HEADER;
|
||||
@@ -67,7 +99,7 @@ class ForwardedHeader {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getProto() {
|
||||
String getProto() {
|
||||
return elements.get("proto");
|
||||
}
|
||||
|
||||
@@ -76,7 +108,7 @@ class ForwardedHeader {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getHost() {
|
||||
String getHost() {
|
||||
return elements.get("host");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user