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)

Reply via email to