[ https://issues.apache.org/jira/browse/CXF-9057?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17886376#comment-17886376 ]
Johannes Herr commented on CXF-9057: ------------------------------------ Hi Andriy, I will create a small project to demonstrate the problem. Might take until next week though. > Chunked Stream is closed regularly when Exception is thrown > ----------------------------------------------------------- > > Key: CXF-9057 > URL: https://issues.apache.org/jira/browse/CXF-9057 > Project: CXF > Issue Type: Bug > Affects Versions: 3.5.8 > Reporter: Johannes Herr > Priority: Major > > In response to SOAP requests served by Apache CXF we send large datasets > streamed directly from a database. Because of the size of the data, chunked > encoding is used. Unfortunately when a database error occurs and an exception > is thrown while data is sent, the client will receive a regular ending to the > chunked data stream. That means he has no way to recognise that an error > occurred and that he has only received a partial file. > To be more specific the response looks somewhat like this: > {code:java} > HTTP/1.1 200 OK > Date: Tue, 10 Sep 2024 16:17:45 GMT > Content-Type: multipart/related; type="application/xop+xml"; > boundary="uuid:49aa53f9-ec29-4f1a-bc07-a21256c2f940"; > start="<root.mess...@cxf.apache.org>"; start-info="text/xml" > Transfer-Encoding: chunked > Server: Jetty(10.0.21) > 8000 > --uuid:49aa53f9-ec29-4f1a-bc07-a21256c2f940 > Content-Type: application/xop+xml; charset=UTF-8; type="text/xml" > Content-Transfer-Encoding: binary > Content-ID: <root.mess...@cxf.apache.org> > <soap:Envelope > xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">[...]</soap:Envelope> > --uuid:49aa53f9-ec29-4f1a-bc07-a21256c2f940 > Content-Type: > Content-Transfer-Encoding: binary > Content-ID: <03d4ea67-6e8b-4d1f-91b0-b63208989f9...@cxf.apache.org> > xxxxxxxxxxxx[...]xxxxxxx > 356 > xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx > 0 > {code} > That means the response ends with the "0" entry, indicating that the transfer > is complete. > What should happen instead is that the response should be closed without > sending the final 0 entry. ([https://stackoverflow.com/a/17203961/136247]) > For example when we use a Servlet to stream data to a client a throw an > exception the result will look something like this: > {code:java} > HTTP/1.1 200 OK > Date: Fri, 13 Sep 2024 09:31:48 GMT > Content-Type: text/plain;charset=utf-8 > Transfer-Encoding: chunked > Server: Jetty(10.0.21) > 8 > Chunk 1 > 8 > Chunk 2 > 8 > Chunk 3 > 8 > Chunk 4 > 8 > Chunk 5 > {code} > Here there is no closing 0 marker. As a result clients can recognise the > error. (Curl will report "curl: (18) transfer closed with outstanding read > data remaining", Chrome "Failed to load resource: > net::ERR_INCOMPLETE_CHUNKED_ENCODING") > CXF should do the same and not end the chunked stream regularly, when an > exception is thrown. > I have tested with Tomcat and Jetty. Both show the same behaviour. > To provide some detail, Exceptions are caught by CXF here: > org/apache/cxf/phase/PhaseInterceptorChain.java:328 > {code:java} > } catch (RuntimeException ex) { > if (!faultOccurred) { > faultOccurred = true; > wrapExceptionAsFault(message, ex); > } > state = State.ABORTED; > } > {code} > The exception is logged, but not rethrown. > If the exception would be thrown, for instance Tomcats ErrorReportValve would > shut down the output and thereby prevent the end of the input and closing 0 > to be written. > org/apache/catalina/valves/ErrorReportValve.java:112 > {code:java} > // Now close immediately to signal to the client that > // something went wrong > response.getCoyoteResponse().action(ActionCode.CLOSE_NOW, > > request.getAttribute(RequestDispatcher.ERROR_EXCEPTION)); > {code} > Without an exception to prevent this, a regular end of the stream will be > written by > org/apache/catalina/connector/CoyoteAdapter.java:371 > response.finishResponse(); > In Summary: CXF ends a chunked encoded stream in a regular way in spite of > exceptions occurring, which makes it impossible for clients to recognise that > they have downloaded partial and therefore corrupt data. -- This message was sent by Atlassian Jira (v8.20.10#820010)