Axios 解压合法 deflate 响应报 invalid stored block lengths
Axios1.20.0的Node HTTP适配器只把0x78开头识别为zlib封装,较小窗口的合法流可能被重复补头。核对编码与客户端路径,保留解压语义。
同一个接口用其他支持压缩的客户端能读,Node中的Axios却报 Z_DATA_ERROR: invalid stored block lengths。如果响应是Content-Encoding: deflate,压缩端又用了较小的zlib窗口,应检查HTTP适配器是否给已有封装重复添加了头。
在Axios1.20.0中,ZlibHeaderTransformStream把首个非空数据块的第一个字节与十进制120,也就是0x78比较。不等于它时,会先补上0x78、0x9C,再送去解压。
合法zlib头不只有0x78
zlib封装中的窗口信息会影响首字节。压缩端采用windowBits为9的合法流,开头可以是0x18、0x95,不需要再加一个32KiB窗口的头。旧判断只认0x78,反而将已经正确的正文变成错误的组合。
这与服务器真的返回损坏数据、把gzip标成deflate或发送原始deflate是不同的情况。不要仅凭Z_DATA_ERROR就认定服务端压缩器坏了;也不能据一次其他客户端成功,忽略本次失败响应是否完整。
先记录Axios实际版本、adapter和Content-Encoding,并在不泄露正文的前提下核对压缩格式。此处针对Node的http适配器,浏览器或fetch适配器可能由运行时处理解压,不能假定沿用同一条代码。
可控制服务端时,明确选择兼容的压缩方式
如果压缩服务由自己维护,可以评估让该接口使用windowBits: 15生成zlib封装,或沿现有HTTP压缩策略改用双方都支持的编码。它会改变压缩器配置,应检查中间代理、缓存的Vary与实际响应,不是给压缩字节简单补两个常量。
暂时避开该编码时,可在专用请求实例中协商identity。下面仅展示需要合并进现有请求配置的一项:
headers: {
'Accept-Encoding': 'identity',
}
这要求服务器和中间层确实遵守协商。发送请求后仍要检查响应编码,不能因为配置里写了identity就认定收到的一定没有压缩。响应体通常会变大,带宽、时限和大小上限也要按实际情况评估,保留原认证和错误处理。
如果服务端仍返回原来的deflate,该设置不是有效规避。不要不断增加重试:相同字节经过同一解码路径通常仍会失败,也可能加重上游负载。
关闭自动解压不是恢复业务正文
decompress: false只能拿到压缩字节。后续若仍把它当UTF-8文本或JSON解析,会把异常移到下一层。确实需要自行解压时,必须先确认封装格式、保持压缩输入与解压输出的大小限制,并使用匹配的解码器;不能把inflateRaw应用到所有带deflate头的响应。
已核对的正式Axios1.20.0仍保留上述单字节判断,不能把开放修补当成已发布修复。验收应覆盖较小窗口、普通窗口和原接口的其他编码,确认最终业务正文完整、长度限制仍有效,而不只是原来的错误文字消失。


