我想使用新的java.net.HttpClient对另一个系统执行一些请求。
出于调试的目的,我希望记录我发送的请求和收到的响应(以及稍后存储在我们的db中)。
如何检索java发送的有效http标头?
我试着得到这样的标题:
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());但它的产出是:
HTTP-Headers:
---
---然而,我的服务器告诉我,它接收到以下Http头:
HTTP-Headers:
---
Connection: Upgrade, HTTP2-Settings
User-Agent: Java-http-client/11
Host: localhost:54113
HTTP2-Settings: AAEAAEAAAAIAAAABAAMAAABkAAQBAAAAAAUAAEAA
Content-Length: 0
Upgrade: h2c
---我有一个多线程应用程序,可能会发生类似的请求。因此,使用带有自定义附加程序的日志框架可能不可靠。
发布于 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对象的代码链中,这证明了这一点。您也不能在客户端进行反射,因为相关的状态( httprequest对象的克隆)不在字段中,它位于局部变量中,反射无法获得这些状态。
HttpRequest可以配置自定义代理,这也不是什么解决方案:这是TCP/IP级代理,而不是HttpRequest,头部是用HTTPS加密发送的。因此,编写(Ab)使用代理设置的代码,以便您可以创建一个“代理”( proxy ),在发送之前首先在您自己的代码周围弹出连接,以查看正在传输的标头,这是非常重要的。
我能给您提供的唯一解决方案是完全抛弃java.net.http.HttpClient,使用一个非java-lib核心库来做您想做的事情。也许是OkHttp。(在您唱完“哈利路亚”之前,我不知道OkHttp是否能够为您提供它打算发送的所有标头,或者给您一种注册钩子的方法,并及时通知您,所以请先进行调查!)
https://stackoverflow.com/questions/67570348
复制相似问题