You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WireMock测试中Java HTTP Client发POST请求遇RST_STREAM异常

WireMock + Java HttpClient POST请求抛出RST_STREAM异常:排查思路与解决方案

问题现象

使用WireMock开展测试时,通过Java HttpClient的HttpRequest.BodyPublishers.ofInputStream()发送POST请求会抛出以下异常:

java.io.IOException: Received RST_STREAM: Stream cancelled
    at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:586)
    at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:123)
    ...(省略剩余栈信息)

但以下场景测试可正常运行:

  • 强制HttpClient使用HTTP/1.1
  • 替换为HttpRequest.BodyPublishers.ofString()构建请求体
  • 改用GET请求

请求dump显示,使用ofInputStream()时请求包含HTTP/2升级头及chunked编码内容:

POST /foo HTTP/1.1
Connection: Upgrade, HTTP2-Settings
Host: localhost:2727
HTTP2-Settings: AAEAAEAAAAIAAAABAAMAAABkAAQBAAAAAAUAAEAA
Transfer-encoding: chunked
Upgrade: h2c
User-Agent: Java-http-client/17.0.6

5
stuff
0

使用ofString()时,上述升级头与chunked编码会消失;强制HTTP/1.1时升级头仍存在,但请求可正常处理。

排查思路

  1. HTTP版本兼容性验证:异常仅在默认HTTP/2模式下触发,强制HTTP/1.1即可恢复正常,说明问题出在WireMock与Java HttpClient的HTTP/2交互逻辑中。
  2. 请求编码差异分析:ofInputStream()默认采用chunked编码,而ofString()会自动设置Content-Length头,避免chunked编码。结合请求dump推测,WireMock对HTTP/2下的chunked编码请求处理存在缺陷。
  3. WireMock版本缺陷排查:当前使用的WireMock 3.3.1可能存在未修复的HTTP/2相关bug,需确认新版本是否解决该问题。

解决方案

方案1:强制使用HTTP/1.1

在构建HttpRequest时显式指定HTTP版本,绕过HTTP/2的兼容性问题:

HttpRequest httpRequest = HttpRequest.newBuilder()
        .uri(URI.create("http://localhost:" + PORT + "/foo"))
        .version(HttpClient.Version.HTTP_1_1) // 强制使用HTTP/1.1
        .POST(HttpRequest.BodyPublishers.ofInputStream(() -> new ByteArrayInputStream("stuff".getBytes(StandardCharsets.UTF_8))))
        .build();

方案2:手动设置Content-Length头

为ofInputStream()请求添加Content-Length头,避免chunked编码,让HTTP/2交互正常进行:

byte[] bodyContent = "stuff".getBytes(StandardCharsets.UTF_8);
HttpRequest httpRequest = HttpRequest.newBuilder()
        .uri(URI.create("http://localhost:" + PORT + "/foo"))
        .header("Content-Length", String.valueOf(bodyContent.length))
        .POST(HttpRequest.BodyPublishers.ofInputStream(() -> new ByteArrayInputStream(bodyContent)))
        .build();

方案3:升级WireMock版本

WireMock后续版本可能修复了HTTP/2兼容性问题,将依赖升级至最新稳定版(如3.5.0+):

<dependency>
    <groupId>org.wiremock</groupId>
    <artifactId>wiremock</artifactId>
    <version>3.5.0</version>
    <scope>test</scope>
</dependency>

原因说明

Java 11+的HttpClient默认优先使用HTTP/2,当使用ofInputStream()且未指定Content-Length时,会采用chunked编码并发起h2c(明文HTTP/2)升级请求。而WireMock 3.3.1的底层服务器在处理这种带chunked编码的h2c升级请求时,无法正确解析请求体,因此主动发送RST_STREAM帧关闭连接。ofString()因自动设置Content-Length避免了chunked编码,强制HTTP/1.1则绕过了HTTP/2处理逻辑,因此均能正常工作。

内容的提问来源于stack exchange,提问作者Mark Schäfer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 19:34:56