标签: java-http-client

如何使用java.net.http.HttpClient记录请求/响应?

实验性地在Java 9中引入的HttpClient现在在Java 11中是稳定的,但毫不奇怪,很少有项目似乎实际使用它.文档几乎不存在.

在进行HTTP调用时,最常见的一个问题是记录请求/响应.你如何使用HttpClient,而不是在每次通话中手动记录它?是否有像所有其他HTTP客户端提供的拦截器机制?

java logging java-9 java-http-client java-11

9
推荐指数
3
解决办法
3267
查看次数

是否可以拦截 Java 11 HttpClient 请求?

基本上如标题所说。Apache HttpClient 和 Spring RestTemplate 允许定义自定义拦截器,这些拦截器环绕请求/响应并允许额外(全局)修改请求参数、日志记录等......

我在标准 Java 实现中没有看到这样的功能java.net.http.HttpClient(从 Java 11 开始)。我是否遗漏了某些东西,或者没有办法在单个上拦截所有请求/响应HttpClient

java http interceptor java-http-client

9
推荐指数
1
解决办法
1739
查看次数

关闭Java HTTP客户端

有没有办法java.net.http.HttpClient立即释放它所持有的资源?

在内部,它包含一个选择器,一个连接池和一个Executor(当使用默认值时).但它没有实现Closeable/ AutoCloseable.

java java-http-client java-11

9
推荐指数
2
解决办法
967
查看次数

Java 11 HttpClient不发送基本身份验证

我编写了以下HttpClient代码,但它没有导致将Authorization标头发送到服务器:

public static void main(String[] args) {
    var client = HttpClient.newBuilder()
            .authenticator(new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("username", "password".toCharArray());
                }
            })
            .version(HttpClient.Version.HTTP_1_1)
            .build();
    var request = HttpRequest.newBuilder()
            .uri("https://service-that-needs-auth.example/")
            .build();
    client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::body)
            .thenAccept(System.out::println)
            .join();
}
Run Code Online (Sandbox Code Playgroud)

我从我正在调用的服务中收到HTTP 401错误.就我而言,它是Atlassian Jira Cloud API.

我已经确认我的getPasswordAuthentication()方法没有被HttpClient调用.

为什么它不起作用,我该怎么做呢?

java http java-http-client java-11

9
推荐指数
1
解决办法
2518
查看次数

如何/在哪里检查 java.net.http.HttpClient HTTP 响应状态代码

Java 11java.net.http.HttpClient似乎不检查 HTTP 状态代码,重定向除外(如果启用)。wiki和 Java API 文档中找到的所有示例始终假设 HTTP 请求是成功的,即它们似乎从不检查响应的状态代码。

这很可能永远不是所需的行为,因为来自 HTTP 500(服务器错误)响应的错误页面可能具有不同的格式或没有格式,因此应用程序无法处理。

应该在哪里检查 HTTP 状态代码?

的文档HttpResponse.BodyHandler包含以下示例片段:

BodyHandler<Path> bodyHandler = (rspInfo) -> rspInfo.statusCode() == 200
    ? BodySubscribers.ofFile(Paths.get("/tmp/f"))
    : BodySubscribers.replacing(Paths.get("/NULL"));
Run Code Online (Sandbox Code Playgroud)

但是,您必须检查两次状态代码,一次在BodyHandler上面显示的情况下,一次在处理响应时(因为尝试从中读取正文"/NULL"会失败)。

对我来说,仅执行 HTTP 状态代码检查似乎是最合理的BodyHandler,例如:

BodyHandler<Path> bodyHandler = (rspInfo) -> {
    if (rspInfo.statusCode() == 200) {
        return BodySubscribers.ofFile(Paths.get("/tmp/f"));
    } else {
        throw new RuntimeException("Request failed");
    }
};
Run Code Online (Sandbox Code Playgroud)

但是,BodyHandler文档没有提及是否允许抛出异常,或者HttpClient在这种情况下会如何表现。

让我感到惊讶的是,JDK 似乎没有提供开箱即用的处理不成功 HTTP 响应的功能,还是我忽略了某些东西?

java java-http-client

9
推荐指数
1
解决办法
5485
查看次数

Java 9 HttpClient java.lang.NoClassDefFoundError:jdk/incubator/http/HttpClient

我正在尝试使用Java 9 maven项目中的孵化器中的HttpClient.我没有得到任何编译问题.该项目成功建立.但是当我尝试运行Main类时,它给了我以下异常:

Exception in thread "main" java.lang.NoClassDefFoundError: jdk/incubator/http/HttpClient
at java9.http_client.Main.main(Main.java:18)
Caused by: java.lang.ClassNotFoundException: jdk.incubator.http.HttpClient
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)....
Run Code Online (Sandbox Code Playgroud)

我的代码只是一个模块信息文件和一个只调用google.com并试图读取响应的Main类:

module-info.java

module java9.http_client {   
    requires jdk.incubator.httpclient;
}
Run Code Online (Sandbox Code Playgroud)

Main.java

public final class Main {

public static void main(String[] args) {
 try {
        HttpClient client = HttpClient.newHttpClient();
        URI httpURI = new URI("http://www.google.com/");
        HttpRequest request = HttpRequest.newBuilder(httpURI).GET().build();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandler.asString());

        String responseBody = response.body();
        int responseStatusCode = response.statusCode();
        System.out.println(responseBody + "\n" + responseStatusCode);

    } catch (URISyntaxException | IOException | …
Run Code Online (Sandbox Code Playgroud)

java java-9 java-module java-http-client

8
推荐指数
1
解决办法
2375
查看次数

如何测试 java.net.http (Java 11) 请求 BodyPublisher?

我正在尝试测试使用新 Java 11 的代码java.net.http.HttpClient

在我的生产代码中,我有这样的事情:

HttpClient httpClient = ... (gets injected)

HttpRequest request = HttpRequest.newBuilder().uri(URI.create("http://localhost:1234"))
        .POST(HttpRequest.BodyPublishers.ofByteArray("example".getBytes()))
        .build();

return httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray());
Run Code Online (Sandbox Code Playgroud)

在我的测试中,我模拟HttpClientjava.net.http.HttpRequest. 如何获取/测试其请求正文(= my "example")?我可以打电话request.bodyPublisher()来获取HttpRequest.BodyPublisher,但后来我被卡住了。

  • 我试图将它转换为jdk.internal.net.http.RequestPublishers.ByteArrayPublisher(它实际上是),但它不会编译,因为模块没有导出相应的包。
  • 我已经检查了HttpRequest.BodyPublisher-interface ( .contentLength(), .subscribe(subscriber)) 中的可用方法,但我想它们是不可能的。
  • 我试图只创建一个新的BodyPublisher并使用 比较它们.equals(),但没有真正的实现,所以比较总是错误的。

java java-http-client java-11

8
推荐指数
1
解决办法
2534
查看次数

Java WebSocket 消息限制

我正在尝试在简单的 Java 应用程序(使用java.net.http.WebSocket类)和google-chrome使用远程运行之间创建通信google-chrome --remote-debugging-port=9222 --user-data-dir=.

发送和接收小消息按预期工作,但在 16kb 大消息的情况下会出现问题。

这是java源代码的一部分:


var uri = new URI("ws://127.0.0.1:9222/devtools/page/C0D7B4DBC53FB39F7A4BE51DA79E96BB");

/// create websocket client
WebSocket ws = HttpClient
    .newHttpClient()
    .newWebSocketBuilder()
    .connectTimeout(Duration.ofSeconds(30))
    .buildAsync(uri, simpleListener)
    .join();

// session Id attached to chrome tab
String sessionId = "...";

// send message
String message = "{\"id\":1,\"method\":\"Runtime.evaluate\",\"params\":{\"expression\":\"document.body.style.backgroundColor = 'blue';\",\"returnByValue\":true,\"awaitPromise\":true,\"userGesture\":true},\"sessionId\":\"" + sessionId + "\"}";

// this works
ws.send(message, true);

// generate big string contains over 18k chars for testing purpose
String bigMessage = "{\"id\":2,\"method\":\"Runtime.evaluate\",\"params\":{\"expression\":\"[" + ("1,".repeat(9000)) + …
Run Code Online (Sandbox Code Playgroud)

java websocket google-chrome-devtools java-http-client chrome-devtools-protocol

8
推荐指数
1
解决办法
1430
查看次数

JDK11 HttpClient 支持预告片标头吗?

我看到 JDK9 中支持预告片(该HttpResponse.trailers\xe2\x80\x8b()方法),但在 JDK 10 上不再支持(该HttpResponse.trailers\xe2\x80\x8b()方法不存在)。

\n

我目前正在使用 JDK11,当我尝试我的请求时:

\n
HttpRequest request = HttpRequest.newBuilder()\n                                 .uri(uri)\n                                 .GET()\n                                 .build();\n\n\nHttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());\n
Run Code Online (Sandbox Code Playgroud)\n

我面对一个java.util.concurrent.ExecutionException: java.io.IOException: no statuscode in response. 仅当我请求带有预告片标题的页面时,它才会失败。\n欢迎任何帮助。谢谢

\n

java java-http-client java-11

8
推荐指数
0
解决办法
265
查看次数

如何使用 Java 的 HttpClient 在慢速流响应主体上超时

当我需要以流方式处理响应时,我应该如何处理使用 Java 11 中包含的 HTTP 客户端挂起发送 HTTP 响应正文的服务器?

已经阅读文档,我知道,这是可以设置在连接超时在请求超时

HttpClient httpClient = HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(2))
        .build();

HttpRequest httpRequest = HttpRequest.newBuilder(URI.create("http://example.com"))
        .timeout(Duration.ofSeconds(5))
        .build();

HttpResponse<Stream<String>> httpResponse = httpClient
        .send(httpRequest, HttpResponse.BodyHandlers.ofLines());

Stream<String> responseLineStream = httpResponse.body();
responseLineStream.count();
Run Code Online (Sandbox Code Playgroud)

在上面的代码中:

  • 如果在 2 秒内无法建立连接,则会抛出超时异常。
  • 如果在 5 秒内没有收到响应,则会抛出超时异常。通过实验,定时器在连接建立后启动,对于这种类型BodyHandler,当收到状态行和报头时,就认为收到了响应。

这意味着当代码执行时,在 7 秒内要么抛出异常,要么到达最后一行。但是,最后一行不受任何超时的限制。如果服务器停止发送响应正文,最后一行将永远阻塞。

在这种情况下,如何防止最后一行挂起?

java http java-http-client java-11

8
推荐指数
2
解决办法
265
查看次数