有没有办法设置主机&Spring HATEOAS `ControllerLinkBuilder` 的端口? [英] Is there a means to set the host & port for the Spring HATEOAS `ControllerLinkBuilder`?

查看:11
本文介绍了有没有办法设置主机&Spring HATEOAS `ControllerLinkBuilder` 的端口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Spring HATEOAS 提供了方便的 ControllerLinkBuilder 来创建到控制器方法的链接,这些链接将作为 hrefs 添加到返回给客户端的 JSON/XML 中.例如:

Spring HATEOAS provides the handy ControllerLinkBuilder to create links to controller methods, which will be added as hrefs in the JSON/XML returned to a client. For instance:

resource.add(linkTo(methodOn(FooController.class)
    .findFoo(entity.getClient().getId()))
    .withRel("show"));

... 可能会像这样生成 JSON:

... might generate JSON a bit like:

{
  "name":"foo", 
  "links":[
    {"rel":"show","href":"http://111.11.11.111:28080/foos/1"}
  ]
}

不过……

我倾向于通过反向代理访问我的服务.我想大多数人可能会这样做.这让我可以在不同的端口上运行多个服务,但让我可以通过相同的基本 URL 访问它们.不幸的是,通过代理访问意味着 Spring HATEOAS 生成的 URL 不是访问资源的有效 URL.

I tend to access my services through a reverse proxy. Which I guess most people probably would. This lets me have multiple services running on different ports, but lets me access them all through the same base URL. Unfortunately, accessing through a proxy means that the URL being generated by Spring HATEOAS is not a URL which is valid for accessing the resource.

现在我可以对链接进行硬编码,但这相当脆弱.让 ControllerLinkBuilder 根据我的控制器 @RequestMapping 配置生成 URL 对我来说很有价值,因为它避免了我的链接与现实不同步的风险.

Now I could just hard-code the links, but that's rather fragile. Having the ControllerLinkBuilder generate URLs based on my controller @RequestMapping configuration is valuable to me, as it avoids the risk of my links getting out of sync with reality.

所以我想知道是否有一个属性可以用来强制设置主机和端口值.我正在使用 Spring Boot,因此理想情况下,我可以将一个属性添加到每个环境中的 application.properties 文件中.

So I was wondering whether there's a property somewhere that I could use to force the host and port values. I'm using Spring Boot, so ideally a property that I could add to the application.properties file in each environment.

注意:

由于这个问题似乎是由 Spring 中的一个错误引起的,我可能应该指出我使用的是 Spring Boot 1.0.2.RELEASE.

As this issue seems to be caused by a bug in Spring, I should probably point out that I'm using Spring Boot 1.0.2.RELEASE.

推荐答案

对我最初提出的问题的纯粹回答似乎涉及编写我自己的 ControllerLinkBuilder 实现,它可以选择构建基于 URL在我设置的环境变量上.我可以这样做.

A pure answer to the question I originally posed seems to involve writing my own ControllerLinkBuilder implementation which has the option of building the URL based on environment variables that I set. I may do that.

但是,我尝试强制使用 URL 的原因是 ControllerLinkBuilder 中存在错误.值得注意的是,这个bug是从ServletUriComponentsBuilder复制的代码中的一个bug.

However, the reason I was trying to force the URL is that there is a bug in the ControllerLinkBuilder. It's worth noting that this bug is a bug in code which was copied from 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 为方案使用默认端口(因此在:"之后没有任何内容),则将使用应用程序端口而不是默认端口.

Basically, the port is only set when the server.port is not 80 or 443, rather than being based on the port used for the request. This means that if the X-Forwarded-Host is using a default port for the scheme (and therefore not having anything after the ":"), then the application port will be used instead of the default.

这篇关于有没有办法设置主机&Spring HATEOAS `ControllerLinkBuilder` 的端口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆