向Wiremock发送multipart HTTP请求时触发MalformedStreamException异常
问题描述
当前基于底层依赖Jetty的Wiremock实现HTTP响应桩化能力,发送multipart类型HTTP请求时,Wiremock/Jetty直接返回500错误,返回的HTML错误页提示抛出MalformedStreamException异常。
该问题在Wiremock从2.31.0升级到2.32.0版本后才出现,通过Postman向桩端点发送的请求信息如下:
请求头
Content-Type: multipart/related; boundary=xxx
请求体
--xxx Content-Type: text/xml; charset=UTF-8 <?xml version="1.0" encoding="utf-8"?> <test></test> --xxx Content-Type: text/xml; charset=UTF-8 <?xml version="1.0" encoding="utf-8"?> <test></test> --xxx--
错误堆栈
Caused by: wiremock.org.apache.commons.fileupload.FileUploadException: Stream ended unexpectedly at wiremock.org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:361) at com.github.tomakehurst.wiremock.http.multipart.PartParser.parseFrom(PartParser.java:51) at com.github.tomakehurst.wiremock.servlet.WireMockHttpServletRequestAdapter.getParts(WireMockHttpServletRequestAdapter.java:286) at com.github.tomakehurst.wiremock.verification.LoggedRequest.createFrom(LoggedRequest.java:71) at com.github.tomakehurst.wiremock.stubbing.InMemoryStubMappings.serveFor(InMemoryStubMappings.java:88) at com.github.tomakehurst.wiremock.core.WireMockApp.serveStubFor(WireMockApp.java:226) at com.github.tomakehurst.wiremock.http.StubRequestHandler.handleRequest(StubRequestHandler.java:57) at com.github.tomakehurst.wiremock.http.AbstractRequestHandler.handle(AbstractRequestHandler.java:69) at com.github.tomakehurst.wiremock.servlet.WireMockHandlerDispatchingServlet.service(WireMockHandlerDispatchingServlet.java:142) at wiremock.javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at wiremock.org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799) at wiremock.org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1631) at wiremock.org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:548) at wiremock.org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) at wiremock.org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440) at wiremock.org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) at wiremock.org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:501) at wiremock.org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) at wiremock.org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355) at wiremock.org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at wiremock.org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:763) at wiremock.org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:146) ... 17 more Caused by: wiremock.org.apache.commons.fileupload.MultipartStream$MalformedStreamException: Stream ended unexpectedly at wiremock.org.apache.commons.fileupload.MultipartStream.readHeaders(MultipartStream.java:570) at wiremock.org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.findNextItem(FileUploadBase.java:1052) at wiremock.org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:1017) at wiremock.org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:309) at wiremock.org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:333) ... 38 more
更新:已针对该问题提交官方bug工单。
解答
这是Wiremock 2.32.0版本引入的已知缺陷,和你构造的multipart请求格式没有关系。
- 2.32.0版本升级了内置shade的Apache Commons FileUpload组件,同时调整了multipart请求的解析逻辑:新解析逻辑严格遵循RFC规范要求multipart分段的所有行终止符必须是CRLF(即
\r\n),只要检测到LF(\n)换行就会判定流格式非法,抛出Stream ended unexpectedly错误。而Postman构造multipart请求时,默认会在很多场景使用LF作为换行符,刚好触发该bug。 - 2.31.0版本的解析逻辑对换行符兼容性更好,同时支持CRLF和LF两种格式,因此升级前不会出现该问题。
可按以下方向排查、解决问题:
- 临时回退Wiremock版本到2.31.0,使用完全相同的请求发送,如果能正常命中桩规则,即可排除请求本身格式错误的可能。
- 抓包确认Postman发出的请求体换行格式,如果是LF换行,手动将所有换行替换为
\r\n后重新发送,2.32.0版本即可正常解析请求。 - 如果业务场景不需要匹配multipart请求内的分段内容,构造Wiremock实例时可直接关闭multipart解析配置,绕开存在缺陷的解析逻辑。
- 长期使用建议直接升级到2.33.0及以上的稳定版本,官方已经在后续迭代中修复了该换行符兼容性问题,无需修改原有请求构造逻辑。
内容的提问来源于stack exchange,提问作者David Spence
相关产品推荐
相关产品推荐

