Johannes Herr created CXF-9057:
----------------------------------
Summary: 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
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="<[email protected]>"; 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: <[email protected]>
<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: <[email protected]>
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)