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

使用InputStream#read(byte[])读取HttpServletRequest请求体时内容不完整

问题根因
  • 核心错误是对InputStream.read(byte[])方法的行为理解存在偏差:该方法不会保证一次性填满传入的字节数组,仅会返回当前可读取的字节数(至多为数组长度)。当请求体数据较大、TCP传输未完全到达缓冲区时,单次调用read只能拿到部分数据,就会出现截断问题。
  • HttpServletRequest#getReader()的readLine()方法内部已实现循环读取逻辑,会一直读取到换行符或流结束位置,因此可以正常获取完整请求体。
  • 现有写法还存在兼容性缺陷:request.getContentLength()仅在非分块传输(请求头带Content-Length字段)的场景下有有效值,如果GitHub Webhook触发的是chunked分块传输请求,该方法会返回-1,会直接导致数组初始化报错。
修复代码
import java.nio.charset.StandardCharsets;

// 完整读取请求体的正确逻辑
InputStream inputStream = request.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int readLen;
// 循环读取直到流结束
while ((readLen = inputStream.read(buffer)) != -1) {
    baos.write(buffer, 0, readLen);
}
byte[] bodyBytes = baos.toByteArray();

// 写入文件逻辑
try (FileWriter fw = new FileWriter(new File("./payload.txt"))) {
    for(byte i : bodyBytes)
        fw.write("0x" + String.format("%02x ", i) + " ");
    fw.write("\n\n\n");
    // 显式指定字符集避免不同环境乱码
    fw.write(new String(bodyBytes, StandardCharsets.UTF_8));
}
额外注意事项
  • 请求体的输入流是消费型的,读取一次就会失效,不要同时调用getInputStream()和getReader(),也不要重复读取同一个流。
  • 如果使用Spring等框架,可直接借助封装好的工具类读取请求体,避免手动处理流的逻辑漏洞。

内容的提问来源于stack exchange,提问作者Sneakyguy6

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 21:39:04