#33 - ControllerLinkBuilder now regards X-Forwarded-Host header.

When setting up the builder we now set the host to the value held in the X-Forwarded-Host [0] header if present. This allows to render appropriate URIs in reverse proxy scenarios. This is essentially an extension of ServletUriComponentsBuilder that will be fixed in there eventually. See SPR-10110 [1] for details.

[0] http://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded-10
[1] https://jira.springsource.org/browse/SPR-10110
This commit is contained in:
Oliver Gierke
2012-12-19 17:34:47 +01:00
parent 25f68fa208
commit 3f8b90e2b5
4 changed files with 70 additions and 17 deletions

View File

@@ -21,6 +21,8 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.core.AnnotationAttribute;
@@ -30,8 +32,12 @@ import org.springframework.hateoas.core.DummyInvocationUtils.LastInvocationAware
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.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriTemplate;
@@ -79,7 +85,7 @@ public class ControllerLinkBuilder extends LinkBuilderSupport<ControllerLinkBuil
Assert.notNull(controller);
ControllerLinkBuilder builder = new ControllerLinkBuilder(ServletUriComponentsBuilder.fromCurrentServletMapping());
ControllerLinkBuilder builder = new ControllerLinkBuilder(getBuilder());
String mapping = DISCOVERER.getMapping(controller);
if (mapping == null) {
@@ -95,7 +101,7 @@ public class ControllerLinkBuilder extends LinkBuilderSupport<ControllerLinkBuil
UriTemplate template = new UriTemplate(DISCOVERER.getMapping(method));
URI uri = template.expand(parameters);
return new ControllerLinkBuilder(ServletUriComponentsBuilder.fromCurrentServletMapping()).slash(uri);
return new ControllerLinkBuilder(getBuilder()).slash(uri);
}
/**
@@ -141,7 +147,7 @@ public class ControllerLinkBuilder extends LinkBuilderSupport<ControllerLinkBuil
values.putAll(accessor.getBoundParameters(invocation));
URI uri = template.expand(values);
return new ControllerLinkBuilder(ServletUriComponentsBuilder.fromCurrentServletMapping()).slash(uri);
return new ControllerLinkBuilder(getBuilder()).slash(uri);
}
/**
@@ -173,4 +179,38 @@ public class ControllerLinkBuilder extends LinkBuilderSupport<ControllerLinkBuil
protected ControllerLinkBuilder createNewInstance(UriComponentsBuilder builder) {
return new ControllerLinkBuilder(builder);
}
/**
* Returns a {@link UriComponentsBuilder} obtained from the current servlet mapping with the host tweaked in case the
* request contains an {@code X-Forwarded-Host} header.
*
* @return
*/
private static UriComponentsBuilder getBuilder() {
HttpServletRequest request = getCurrentRequest();
ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromServletMapping(request);
String header = request.getHeader("X-Forwarded-Host");
if (StringUtils.hasText(header)) {
builder.host(header);
}
return builder;
}
/**
* Copy of {@link ServletUriComponentsBuilder#getCurrentRequest()} until SPR-10110 gets fixed.
*
* @return
*/
private static HttpServletRequest getCurrentRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
Assert.state(requestAttributes != null, "Could not find current request via RequestContextHolder");
Assert.isInstanceOf(ServletRequestAttributes.class, requestAttributes);
HttpServletRequest servletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
Assert.state(servletRequest != null, "Could not find current HttpServletRequest");
return servletRequest;
}
}