#257 - Added support for Forwarded and X-Forwarded-Proto headers.
ControllerLinkBuilder now favors the value of the Forwarded and X-Forwarded-Proto header to build the scheme for the link created. For more information on the Forwarded header, see http://tools.ietf.org/html/rfc7239. Related issue: #107.
This commit is contained in:
committed by
Oliver Gierke
parent
7d0a76a54b
commit
994347c005
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.hateoas.mvc;
|
||||
|
||||
import static org.springframework.util.StringUtils.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
|
||||
@@ -26,7 +28,6 @@ import org.springframework.hateoas.core.DummyInvocationUtils;
|
||||
import org.springframework.hateoas.core.LinkBuilderSupport;
|
||||
import org.springframework.hateoas.core.MappingDiscoverer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
@@ -186,24 +187,29 @@ public class ControllerLinkBuilder extends LinkBuilderSupport<ControllerLinkBuil
|
||||
HttpServletRequest request = getCurrentRequest();
|
||||
ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromServletMapping(request);
|
||||
|
||||
ForwardedHeader forwarded = ForwardedHeader.of(request.getHeader(ForwardedHeader.NAME));
|
||||
String proto = hasText(forwarded.getProto()) ? forwarded.getProto() : request.getHeader("X-Forwarded-Proto");
|
||||
String forwardedSsl = request.getHeader("X-Forwarded-Ssl");
|
||||
|
||||
if (StringUtils.hasText(forwardedSsl) && forwardedSsl.equalsIgnoreCase("on")) {
|
||||
if (hasText(proto)) {
|
||||
builder.scheme(proto);
|
||||
} else if (hasText(forwardedSsl) && forwardedSsl.equalsIgnoreCase("on")) {
|
||||
builder.scheme("https");
|
||||
}
|
||||
|
||||
String host = request.getHeader("X-Forwarded-Host");
|
||||
String host = forwarded.getHost();
|
||||
host = hasText(host) ? host : request.getHeader("X-Forwarded-Host");
|
||||
|
||||
if (!StringUtils.hasText(host)) {
|
||||
if (!hasText(host)) {
|
||||
return builder;
|
||||
}
|
||||
|
||||
String[] hosts = StringUtils.commaDelimitedListToStringArray(host);
|
||||
String[] hosts = commaDelimitedListToStringArray(host);
|
||||
String hostToUse = hosts[0];
|
||||
|
||||
if (hostToUse.contains(":")) {
|
||||
|
||||
String[] hostAndPort = StringUtils.split(hostToUse, ":");
|
||||
String[] hostAndPort = split(hostToUse, ":");
|
||||
|
||||
builder.host(hostAndPort[0]);
|
||||
builder.port(Integer.parseInt(hostAndPort[1]));
|
||||
@@ -215,7 +221,7 @@ public class ControllerLinkBuilder extends LinkBuilderSupport<ControllerLinkBuil
|
||||
|
||||
String port = request.getHeader("X-Forwarded-Port");
|
||||
|
||||
if (StringUtils.hasText(port)) {
|
||||
if (hasText(port)) {
|
||||
builder.port(Integer.parseInt(port));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2014 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
|
||||
*
|
||||
* http://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.hateoas.mvc;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Value object to partially implement the {@literal Forwarded} header defined in RFC 7239.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @see http://tools.ietf.org/html/rfc7239
|
||||
*/
|
||||
class ForwardedHeader {
|
||||
|
||||
public static String NAME = "Forwarded";
|
||||
private static final ForwardedHeader NO_HEADER = new ForwardedHeader(Collections.<String, String> emptyMap());
|
||||
|
||||
private final Map<String, String> elements;
|
||||
|
||||
private ForwardedHeader(Map<String, String> elements) {
|
||||
this.elements = elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ForwardedHeader} from the given source.
|
||||
*
|
||||
* @param source can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static ForwardedHeader of(String source) {
|
||||
|
||||
if (!StringUtils.hasText(source)) {
|
||||
return NO_HEADER;
|
||||
}
|
||||
|
||||
Map<String, String> elements = new HashMap<String, String>();
|
||||
|
||||
for (String part : source.split(";")) {
|
||||
|
||||
String[] keyValue = part.split("=");
|
||||
|
||||
if (keyValue.length != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
elements.put(keyValue[0].trim(), keyValue[1].trim());
|
||||
}
|
||||
|
||||
Assert.notNull(elements, "Forwarded elements must not be null!");
|
||||
Assert.isTrue(!elements.isEmpty(), "At least one forwarded element needs to be present!");
|
||||
|
||||
return new ForwardedHeader(elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value defined for the {@code proto} parameter of the header.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getProto() {
|
||||
return elements.get("proto");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value defined for the {@code host} parameter of the header.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getHost() {
|
||||
return elements.get("host");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user