java - block 末尾的意外内容 - 是什么构建了损坏的流?

标签 java spring http tomcat chunked-encoding

我正在访问一个返回大约 900k XML 的端点。我时不时地(在今天的测试中不到 5000 分之一)我得到一个 MalformedChunkCodingException

这是从一个相当老的 web 应用程序(约 10 年)发生的,它基于 Spring 3 构建。我转而使用 RestTemplate 而不是直接使用 httpclient,但这并没有解决它。今天在 httpclient 上启用了线级日志记录的情况下运行了几个小时后,我设法捕获了一个。

Caused by: org.apache.http.MalformedChunkCodingException: Unexpected content at the end of chunk
    at org.apache.http.impl.io.ChunkedInputStream.getChunkSize(ChunkedInputStream.java:259)
    at org.apache.http.impl.io.ChunkedInputStream.nextChunk(ChunkedInputStream.java:227)
    at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:186)
    at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:137)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.Reader.read(Reader.java:140)
    at org.springframework.util.StreamUtils.copyToString(StreamUtils.java:74)
    at org.springframework.http.converter.StringHttpMessageConverter.readInternal(StringHttpMessageConverter.java:85)
    at org.springframework.http.converter.StringHttpMessageConverter.readInternal(StringHttpMessageConverter.java:40)
    at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:153)
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:103)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:724)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:709)

通常日志似乎是这样的:

DEBUG org.apache.http.wire - << "words words words"
DEBUG org.apache.http.wire - << "[\r][\n]"
DEBUG org.apache.http.wire - << "FAF[\r][\n]"
DEBUG org.apache.http.wire - << "words words words up to FAF bytes" 
DEBUG org.apache.http.wire - << "[\r][\n]"
DEBUG org.apache.http.wire - << "BAA[\r][\n]"
DEBUG org.apache.http.wire - << "words words words up to BAA bytes"

但是在那个出错的地方我有这个:

DEBUG org.apache.http.wire - << "words words words"
DEBUG org.apache.http.wire - << "[\r][\n]"
DEBUG org.apache.http.wire - << "B50[\r][\n]"
DEBUG org.apache.http.wire - << "words words words up to B50 bytes"
DEBUG org.apache.http.wire - << "3FC0[\r][\n]"

它缺少 B50 block 末尾的 [\r][\n]。

所以,假设我可以信任 org.apache.http.wire 调试,那么我的应用程序正在接收这样的流,而且它的格式是错误的。它们之间的 haproxy 是否有可能破坏流?

幸运与否,对话的另一端也是我的一个应用程序,运行在 tomcat 和 Spring 4.2.4 中。

我从哪里开始寻找谁在构建无效响应? Spring ? Tomcat ?

看起来我可以禁用分块,但只能在构建响应时计算我的内容长度,我不太愿意这样做,因为那样我就必须手动序列化我的响应,而不是让 Spring做吧。

最佳答案

正如您所说,该应用程序很旧。您可能需要更新所有库版本,希望该问题已在某处检测到并修复。

但是找到不良行为者会有所帮助,因为您只需要修复那个。

根据我自己在 HTTP 工具中测试错误语法支持的经验,我很确定 Haproxy 是您列出的元素中更强大的元素。但这并不排除那里的问题。

发送端点和接收端点之间的每个 HTTP actor 都可以更改 HTTP 主体(修改 block 大小),因此您需要捕获所有 actor(spring、tomcat、haproxy、任何其他代理和/或反向)的输入和输出代理、负载均衡器、ssl 终结器)来检测坏 block 。我将从消息发射器、XML 端点开始。我会使用 wireshark/pcap/httpdump,这是真正捕获 TCP 和 HTTP 流量的东西。但是您可能必须找到一种方法来快速丢弃捕获,直到您到达失败点,因为 1/5000 意味着您有捕获大量数据的巨大风险。

关于java - block 末尾的意外内容 - 是什么构建了损坏的流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57732129/

相关文章:

java - 在哪里下载 DB2 8.1 的 jdbc 驱动程序?

django - 如何限制用户使用浏览器 "back button"返回上一页(改为重定向到不同的页面)?

java - 函数发送不可解码的文本 Android/Java

c++ - HTTP GET请求问题

java - 如何使用 iText 旋转 PDF 中的水印(文本)?

java - 有没有办法列出应用程序中的所有 Web 服务?

java - 同步,不总是正确的?

java - 使用basename在java中命名输出文件

java - Spring 乐观锁定 :How to retry transactional method till commit is successful

Spring Data JPA 之类的项目不依赖于 Spring