首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何获得所有有效的HTTP请求头?

如何获得所有有效的HTTP请求头?
EN

Stack Overflow用户
提问于 2021-05-17 13:09:13
回答 1查看 1K关注 0票数 0

我想使用新的java.net.HttpClient对另一个系统执行一些请求。

出于调试的目的,我希望记录我发送的请求和收到的响应(以及稍后存储在我们的db中)。

如何检索java发送的有效http标头?

我试着得到这样的标题:

代码语言:javascript
复制
HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("http://localhost:54113"))
        .build();

System.out.println("HTTP-Headers:\n---");
request.headers().map()
        .forEach((key, values) ->
                values.forEach(value ->
                        System.out.println(key + ": " + value)
                )
        );
System.out.println("---");

HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());

但它的产出是:

代码语言:javascript
复制
HTTP-Headers:
---
---

然而,我的服务器告诉我,它接收到以下Http头:

代码语言:javascript
复制
HTTP-Headers:
---
Connection: Upgrade, HTTP2-Settings
User-Agent: Java-http-client/11
Host: localhost:54113
HTTP2-Settings: AAEAAEAAAAIAAAABAAMAAABkAAQBAAAAAAUAAEAA
Content-Length: 0
Upgrade: h2c
---

我有一个多线程应用程序,可能会发生类似的请求。因此,使用带有自定义附加程序的日志框架可能不可靠。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-17 13:38:08

我对你的问题有一个不幸的答案:遗憾的,不可能的

关于为什么会出现这种情况的一些背景:

普通的基于OpenJDK的java核心库实现所使用的HttpRequest的实际实现是而不是 java.net.http.HttpRequest --这只是一个接口。我是jdk.internal.net.http.HttpRequestImpl

这段代码有两个单独的标题列表要发送;一个是“用户标题”,另一个是“系统标题”。您的.headers()调用只检索用户头,这些标头是您明确要求发送的标头,当然,由于您要求没有发送,所以它是空的。

系统标头是这6个标头的来源。我不认为有什么办法能以一种支持的方式得到这些。如果您想使用不受支持的策略(您编写的代码查询内部状态,因此无法保证在其他JVM实现或基本JVM实现的未来版本上工作),不幸的是,这仍然是相当困难的!一些基本的思考并不能在这里完成工作。这是最坏的消息:

  • 在调用send之前,根本不设置这6个标头。例如,与HTTP2相关的三个标头是在包-私有setH2Upgrade方法中设置的,该方法被传递给HttpClient对象,这证明除了调用send时启动的事件链之外,不可能调用该对象。HttpClient对象不存在于生成HttpRequest对象的代码链中,这证明了这一点。
  • 更糟糕的是,默认的HttpClient impl将首先克隆您的HttpRequest,然后在此克隆上执行一系列操作(包括添加那些系统头),然后发送克隆,这意味着您拥有的HttpRequest对象没有任何这些头。即使在发送呼叫完成之后也不会。因此,即使您不介意在发送之后获取这些标头,并且也可以使用反射来挖掘内部状态来获取它们,它也是行不通的。

您也不能在客户端进行反射,因为相关的状态( httprequest对象的克隆)不在字段中,它位于局部变量中,反射无法获得这些状态。

HttpRequest可以配置自定义代理,这也不是什么解决方案:这是TCP/IP级代理,而不是HttpRequest,头部是用HTTPS加密发送的。因此,编写(Ab)使用代理设置的代码,以便您可以创建一个“代理”( proxy ),在发送之前首先在您自己的代码周围弹出连接,以查看正在传输的标头,这是非常重要的。

我能给您提供的唯一解决方案是完全抛弃java.net.http.HttpClient,使用一个非java-lib核心库来做您想做的事情。也许是OkHttp。(在您唱完“哈利路亚”之前,我不知道OkHttp是否能够为您提供它打算发送的所有标头,或者给您一种注册钩子的方法,并及时通知您,所以请先进行调查!)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67570348

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档