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

Spring REST服务报Invalid chunk header异常及400错误求助

Spring REST控制器处理application/octet-stream时的Invalid chunk header异常排查

首先,先梳理下你的问题场景:你有一个接收application/octet-stream类型请求的Spring REST控制器,通过@RequestBody byte[]解析GZ文件请求体,但部分请求会抛出HttpMessageNotReadableException,嵌套异常为java.io.IOException: Invalid chunk header,最终返回客户端400响应。你的控制器代码如下:

public ResponseEntity<String> test(@RequestBody byte[] request, @RequestHeader HttpHeaders headers, HttpServletRequest servletRequest) {}

对应的核心异常栈:

org.springframework.http.converter.HttpMessageNotReadableException: I/O error while reading input message; nested exception is java.io.IOException: Invalid chunk header
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:229) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    ...
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(...)

异常原因分析

这个错误本质是HTTP分块传输编码(Chunked Transfer Encoding)的解析失败,常见触发原因有以下几种:

  • 客户端请求格式不规范:如果客户端使用分块编码发送请求,但分块头部不符合HTTP规范(比如不是有效的十六进制数字,或者缺少分块结束标记0\r\n\r\n),Tomcat的解析器就会抛出该异常。
  • 中间代理/网关篡改请求:如果请求经过Nginx、Apache等反向代理,代理的某些配置(比如proxy_buffering、自动修改Transfer-Encoding头)可能破坏分块数据格式,导致后端解析失败。
  • 框架/容器版本bug:你使用的Spring 4.3.10和Tomcat 7.0.57都是较老的版本,这两个组件在早期版本中确实存在一些分块解析的已知问题,比如处理特殊分块场景时的逻辑漏洞。
  • 请求头冲突:如果请求同时设置了Content-Length和Transfer-Encoding: chunked,这种不符合HTTP规范的请求会让解析器陷入混乱,触发异常。

解决方法

针对上述原因,你可以按以下步骤排查和修复:

  1. 验证客户端请求的正确性

    • 让客户端检查请求是否合规:确保分块头部是有效的十六进制字符串,且请求末尾带有正确的结束块(0\r\n\r\n)。
    • 如果客户端不需要分块传输,建议直接发送带Content-Length头的请求,避免分块编码带来的解析风险。
  2. 检查中间代理配置

    • 若存在反向代理(如Nginx),检查是否有修改分块数据的配置:比如关闭proxy_buffering(或调整相关参数),确保代理不会篡改Transfer-Encoding头和分块内容。
    • 确认代理没有自动添加/删除请求头,导致请求格式不符合HTTP规范。
  3. 升级框架和容器版本

    • 升级到Spring 4.3.x系列的最新稳定版(如4.3.30.RELEASE),该版本修复了很多早期的消息解析bug。
    • 同步升级Tomcat到7.0.x的最新补丁版(如7.0.109),Tomcat在后续版本中修复了不少分块解析的问题。
  4. 绕过Spring消息转换器,手动读取请求体
    如果上述方法无效,可以尝试直接从HttpServletRequest获取输入流读取数据,跳过Spring的@RequestBody解析逻辑:

    import org.apache.commons.io.IOUtils; // 可使用Apache Commons IO,或自行实现流读取逻辑
    
    public ResponseEntity<String> test(HttpServletRequest servletRequest, @RequestHeader HttpHeaders headers) throws IOException {
        // 直接读取原始输入流
        InputStream inputStream = servletRequest.getInputStream();
        byte[] requestBytes = IOUtils.toByteArray(inputStream);
        
        // 后续处理GZ文件的业务逻辑
        // ...
        
        return ResponseEntity.ok("处理完成");
    }
    

    这种方式能直接获取原始请求数据,避免Spring消息转换器在分块解析时出错。

  5. 自定义消息转换器配置
    你也可以尝试自定义ByteArrayHttpMessageConverter,调整其解析行为:

    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            ByteArrayHttpMessageConverter converter = new ByteArrayHttpMessageConverter();
            converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM));
            converters.add(0, converter); // 优先使用自定义转换器
            super.configureMessageConverters(converters);
        }
    }
    

    确保转换器正确支持application/octet-stream类型,且无额外解析逻辑干扰分块数据读取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:48:52