当前位置: 首页 > 知识库问答 >
问题:

有没有办法设置主机

孙博艺
2023-03-14

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

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中的一个bug引起的,我可能应该指出,我使用的是Spring Boot 1.0.2。释放。

共有2个答案

易衡
2023-03-14

Spring-Boot使用较旧版本的Spring-HATEOAS,我认为他们添加了对X-Forwarded-Port和X-Forwarded-Ssl标头的支持是0.11,只需将该显式版本添加到您的POM,如果您的代理正在做正确的事情并添加这些标头,您应该可以开始了。

此外,如果您的代理可以配置为不重写主机标头,则内置的控制器链接生成器将正常工作。

赏航
2023-03-14

对我最初提出的问题的纯粹回答似乎涉及编写我自己的ControlllerLinkBuilder实现,它可以选择根据我设置的环境变量构建URL。我可能会这么做。

但是,我尝试强制URL的原因是ControlllerLinkBuilder中存在错误。值得注意的是,此错误是从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为方案使用默认端口(因此在 ":"), 之后没有任何内容,则将使用应用程序端口而不是默认端口。

 类似资料:
  • 问题内容: 我可以看到文档说我们可以在文档上设置,但不能在索引/索引上设置。还想知道如果我们设置它是否对性能有影响。 问题答案: 已为每个索引启用,但有效期为每个文档。 如果您希望索引“过期”,请删除它们。更简单,更高效。 是的,对性能有影响。Elasticsearch处理“过期”数据的“方式”是创建基于时间的索引。意思是,您每天或每周都会创建一个索引。在该索引中索引属于该日/周的所有内容。您决定

  • 问题内容: 来自目标C的您可以在2个对象之间调用函数以使它们维护一个引用,如果在运行时您不希望在删除该对象的引用之前也不要破坏该对象的话,这会很方便。迅捷有与此类似的东西吗? 问题答案: 这是一个从jckarter的答案衍生而来的简单但完整的示例。 它显示了如何向现有类添加新属性。它通过在扩展块中定义计算属性来实现。计算的属性存储为关联的对象: 编辑: 如果需要支持获取未初始化属性的值并避免发生错

  • 我在本地计算机上将一条太大的消息推送到Kafka消息主题中,现在我收到一个错误: 增加在这里并不理想,因为我实际上不想接受那么大的消息。

  • 问题内容: 我来自iOS开发,我想知道是否可以像iOS中那样以编程方式设置?并添加in代码。还是设置a 使用绑定的唯一方法? 谢谢! 问题答案: 感谢@stevesliva为我指出了 。我将其转换为Swift。这就是我得到的。 我在ViewController中创建一个NSCollectionView: 在ViewController中创建的CollectionViewItem只需加载一个视图,即

  • 有没有办法(一步一步)在M1 Mac上设置PyCharm?我正在寻找一些一步一步地如何克服口译员的错误。还有一个错误消息发生在我的简单Hello world打印中。 “进程结束,退出代码137(被信号9:SIGKILL中断)”

  • 问题内容: 我正在使用LESS样式语言。 考虑以下CSS: 现在,我所有的图像都在文件夹中,我希望能够将变量设置为图像路径并像这样使用它: 但是,这不起作用。这没什么大不了的,如果映像文件夹发生更改,我总是可以使用 查找和替换 。我刚刚开始学习LESS,并且想知道是否有可能这样做。 问题答案: 尝试将字符串插值用于此类情况。在docs中寻找“变量插值” 。