WireMock处理SOAP MTOM带附件请求报Buffer size exceeded错误
SOAP MTOM + WireMock 请求报IO异常问题
问题相关代码
@Test public void AfpToPdf() throws Exception { stubWireMock(FOLDER_PATH, "convertAfpToPdf", 200, RECUPERA_DOCUMENTO_FOLDER_RESPONSE_OK); ConvertAfpToPdfType request = createDocumentoAFPRequest(); Testata testata = new Testata(); ConvertAfpToPdfResponseType response = getPortNew().convertAfpToPdf(request, testata, new Holder<>()); assertNotNull(response); } private ConvertAfpToPdfType createDocumentoAFPRequest() { ConvertAfpToPdfType request = new ConvertAfpToPdfType(); ListaFileAfpType listaFileAfpType = new ListaFileAfpType(); DataHandler dataHandlerAFP = new DataHandler(new FileDataSource("FOLD14.R00407A.NT01.D130606.AFP")); listaFileAfpType.setDocumentFileAfp(dataHandlerAFP); request.setListaFileAfp(listaFileAfpType); return request; } protected void stubWireMock(String urlPath, String requestContained, int httpStatus, String bodyFileName) { wireMockRule.stubFor(post(urlPathEqualTo((BASE_URL_CONVERSIONE))) .withRequestBody(containing("conversioneAfp")) .willReturn( aResponse() .withStatus(200) .withHeader("Content-Type", "multipart/form-data") .withBody("prova"))); }
异常堆栈
java.io.IOException: Buffer size exceeded: no line terminator at org.eclipse.jetty.util.ReadLineInputStream.readLine(ReadLineInputStream.java:68) at org.eclipse.jetty.util.MultiPartInputStreamParser.parse(MultiPartInputStreamParser.java:619) at org.eclipse.jetty.util.MultiPartInputStreamParser.getParts(MultiPartInputStreamParser.java:491) at org.eclipse.jetty.server.Request.getParts(Request.java:2374) at org.eclipse.jetty.server.Request.getParts(Request.java:2326) at com.github.tomakehurst.wiremock.servlet.WireMockHttpServletRequestAdapter.safelyGetRequestParts(WireMockHttpServletRequestAdapter.java:295) at com.github.tomakehurst.wiremock.servlet.WireMockHttpServletRequestAdapter.getParts(WireMockHttpServletRequestAdapter.java:279) at com.github.tomakehurst.wiremock.verification.LoggedRequest.createFrom(LoggedRequest.java:70) at com.github.tomakehurst.wiremock.stubbing.InMemoryStubMappings.serveFor(InMemoryStubMappings.java:76) at com.github.tomakehurst.wiremock.core.WireMockApp.serveStubFor(WireMockApp.java:164) at com.github.tomakehurst.wiremock.http.StubRequestHandler.handleRequest(StubRequestHandler.java:50) at com.github.tomakehurst.wiremock.http.AbstractRequestHandler.handle(AbstractRequestHandler.java:44) at com.github.tomakehurst.wiremock.servlet.WireMockHandlerDispatchingServlet.service(WireMockHandlerDispatchingServlet.java:108) at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:841) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:543) at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253) at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:481) at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144) at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:666) at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) at org.eclipse.jetty.server.Server.handle(Server.java:531) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:352) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260) at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305) at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683) at java.lang.Thread.run(Thread.java:750)
根因说明
异常和业务测试代码逻辑无关,是WireMock和Jetty的适配问题:WireMock记录请求时会自动调用Jetty内置的MultiPartInputStreamParser,尝试解析所有Content-Type带multipart标识的请求。SOAP MTOM传输二进制附件的分块格式和Jetty默认支持的multipart/form-data规范不兼容,二进制分块缺失标准行终止符,直接触发Jetty读行逻辑的缓冲区超限报错。
解决方案
- 优先升级WireMock到2.27.0及以上版本,高版本已针对非标准multipart请求做容错处理。初始化WireMock规则时增加配置关闭请求自动解析,即可完全绕开报错:
WireMockRule wireMockRule = new WireMockRule(wireMockConfig() .port(8080) .disableRequestAudit() );
- 若暂时无法升级WireMock版本,直接调整桩配置:一是不要使用任何会触发multipart解析的匹配规则,仅保留URL和SOAP报文固定文本段的匹配逻辑;二是修正响应头配置,SOAP接口响应无需设置
Content-Type: multipart/form-data,改为text/xml;charset=UTF-8,避免响应侧也触发不必要的解析逻辑。 - 临时调试场景可直接在SOAP客户端关闭MTOM特性,将附件转base64编码后直接放在SOAP报文节点中传输,请求不再走multipart格式即可规避报错,调试完成后再恢复MTOM配置。
内容的提问来源于stack exchange,提问作者Lore
相关产品推荐
相关产品推荐

