Spring HATEOAS提供了方便的ControllerLinkBuilder
来创建控制器方法的链接,这些方法将作为返回给客户端的JSON / XML中的hrefs添加。例如:
resource.add(linkTo(methodOn(FooController.class)
.findFoo(entity.getClient().getId()))
.withRel("show"));
...可能会生成JSON,如:
{
"name":"foo",
"links":[
{"rel":"show","href":"http://111.11.11.111:28080/foos/1"}
]
}
...然而
我倾向于通过反向代理访问我的服务。我猜大多数人可能会这样。这让我可以在不同的端口上运行多个服务,但是我可以通过相同的基本URL访问它们。不幸的是,通过代理访问意味着Spring HATEOAS生成的URL不是对访问资源有效的URL。
现在我可以对链接进行硬编码,但这相当脆弱。让ControllerLinkBuilder
生成基于我的控制器@RequestMapping
配置的URL对我来说很有价值,因为它避免了我的链接与现实不同步的风险。
所以我想知道是否有某个属性可以用来强制主机和端口值。我使用的是Spring Boot,理想情况下,我可以添加到每个环境中的application.properties
文件中。
注意:
由于这个问题似乎是由Spring中的一个错误引起的,我应该指出我使用的是Spring Boot 1.0.2.RELEASE。
答案 0 :(得分:4)
我最初提出的问题的纯粹答案似乎涉及编写我自己的ControllerLinkBuilder
实现,该实现可以根据我设置的环境变量构建URL。我可以这样做。
但是,我试图强制使用网址的原因是ControllerLinkBuilder
中存在错误。值得注意的是,此错误是代码中的错误,该错误是从ServletUriComponentsBuilder
复制的。
String scheme = request.getScheme();
// The port number retrieved here is the port set by server.port
int port = request.getServerPort();
String host = request.getServerName();
String header = request.getHeader("X-Forwarded-Host");
if (StringUtils.hasText(header)) {
String[] hosts = StringUtils.commaDelimitedListToStringArray(header);
String hostToUse = hosts[0];
if (hostToUse.contains(":")) {
String[] hostAndPort = StringUtils.split(hostToUse, ":");
host = hostAndPort[0];
// Note that the port is set if there is a ":" in the address.
port = Integer.parseInt(hostAndPort[1]);
}
else {
host = hostToUse;
}
}
ServletUriComponentsBuilder builder = new ServletUriComponentsBuilder();
builder.scheme(scheme);
builder.host(host);
// Here lies the bug...
if ((scheme.equals("http") && port != 80) || (scheme.equals("https") && port != 443)) {
builder.port(port);
}
基本上,端口仅在server.port
不是80或443时设置,而不是基于用于请求的端口。这意味着如果X-Forwarded-Host
正在使用该方案的默认端口(因此在":"之后没有任何内容),则将使用应用程序端口而不是默认端口。 / p>
答案 1 :(得分:1)
Spring-Boot使用旧版本的Spring-HATEOAS,我认为它们是.11,他们添加了对X-Forwarded-Port和X-Forwarded-Ssl标头的支持,只需将该显式版本添加到您的POM中,如果您的代理正在做正确的事情并添加那些你应该好的标题。
此外,如果您的代理可以配置为不重写HOST标头,则内置控制器链接构建器可以正常工作。