【问题标题】:How to customise "host" header in Java http client如何在 Java http 客户端中自定义“主机”标头
【发布时间】:2018-12-31 00:27:07
【问题描述】:

这是我的代码:

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("http://127.0.0.1:8081/"))
    .header("Host", "test.example.com")
    .build();
client.send(request, HttpResponse.BodyHandlers.ofString());

结果我看到上面的代码发送:

GET / HTTP/1.1
Connection: Upgrade, HTTP2-Settings
Content-Length: 0
Host: 127.0.0.1:8081
HTTP2-Settings: AAEAAEAAAAIAAAABAAMAAABkAAQBAAAAAAUAAEAA
Upgrade: h2c
User-Agent: Java-http-client/10
Host: test.example.com

如您所见,它发送两个 Host 标头(一个来自 URI 和一个我指定的),但我希望它发送我指定的 Host 标头,而不是来自 URI 的那个。 这个客户端可以吗?

编辑:在 Java 11 中,情况变得更糟(您需要将 client.send 行更改为:client.send(request, HttpResponse.BodyHandlers.ofString());):

java.lang.IllegalArgumentException: restricted header name: "Host"

如何自定义该标头(测试虚拟主机所需)?

我也尝试了setHeader 并得到完全相同的问题(双Host 标头,或异常)。

编辑:我报告了JDK bug

【问题讨论】:

    标签: java http2 java-10 java-11 java-http-client


    【解决方案1】:

    从 Java 12(EA bu​​ild 22)开始,它已通过附加属性 jdk.httpclient.allowRestrictedHeaders 解决(请参阅 https://bugs.openjdk.java.net/browse/JDK-8213696)。

    所以现在可以通过执行以下代码来覆盖Host(或任何其他受限制的标头): java -Djdk.httpclient.allowRestrictedHeaders=host ...

    【讨论】:

      【解决方案2】:

      Java11 客户端代码的行为似乎是正确的。 Host 部分详细说明了细节。顺便说一句,来自HttpRequest builder header(String name, String value) 的文档:

      *    @throws IllegalArgumentException if the header name or value is not
      *    valid, see <a href="https://www.rfc-editor.org/rfc/rfc7230#section-3.2">
      *    RFC 7230 section-3.2</a>, or the header name or value is restricted
      *    by the implementation.
      

      更新:看到这个,回答pertaining to JDK/12

      【讨论】:

      • 是的,但是例如一段时间以来,Apache HttpClient 允许自定义该标头:stackoverflow.com/questions/6045911/… 同样 curl 允许自定义 Host 标头(它优先于 URL)。因此,在这个 http 客户端中具有相同的功能是合理的期望。
      • @KrzysztofKrasoń 虽然我无法定义其他客户端的实现不同的原因。然而,我可以进一步深入研究的是,RFC2616 指定了相同的内容,what is the http host header 的答案还强调了 URI 应该是这样的,即应该从中读取主机和端口。
      • 虽然您根据 RFC 是正确的,但几乎所有 Web 客户端都允许某种程度的自定义 - 这对开发人员来说非常方便,例如我希望能够覆盖给定 http 客户端生成的所有标头 - 这可以轻松调试正在开发的应用程序。
      • 这是 java 11 的正确答案,希望它在下一个版本中有所改变。
      猜你喜欢
      • 2017-01-19
      • 2021-06-12
      • 2020-07-11
      • 2015-03-27
      • 2017-12-20
      • 1970-01-01
      • 2021-09-02
      • 1970-01-01
      • 2011-03-11
      相关资源
      最近更新 更多