Hi.

I'm using Apache CXF 3.1.5 as a JAX-RS client implementation and recently 
encountered
a stream corruption bug when using client side JAX-RS filters.

In my scenario, I use a JAX-RS client side filter to perform response logging 
while
using client side JAX-RS proxies.

For that I created a JAX-RS filter implementing ClientRequestFilter and 
ClientResponseFilter
and added it as a provider to the JAX-RS/CXF runtime.

Now when I perform e.g. a GET request, the filter is invoked as expected calling

@Override
public void filter(ClientRequestContext requestContext, ClientResponseContext 
responseContext) throws IOException {

        if (responseContext.hasEntity()) {
                // wrap responseContext.getEntityStream() with 
LoggingBufferedStream and set it on responseContext
                ...
        }
}

with the current response.

Now from time to time it happened, that the received content missed the first 
byte of
the payload leading to an exception in jackson, that it couldn't parse the JSON 
content
correctly.

After investigation, this happend most of the time, when the response had
"transfer-encoding: chunked" set. Looking deeper into CXFs 
responseContext.hasEntity()
implementation showed, that the lost byte is due to a call to 
IOUtils.isEmpty(stream):

https://github.com/apache/cxf/blob/master/core/src/main/java/org/apache/cxf/helpers/IOUtils.java

In there are basically 3 checks:

- is mark supported?
- is available > 0
- if NOT the above, wrap stream with PushbackInputStream, try to read a byte 
and unread.

Sadly, in this chunked scenario, it seems that the 
responseContext.getEntityStream()
neither supports mark nor is available > 0 (it is 0). So it wraps the stream 
with
PushbackInputStream, reads a byte and unreads. But, as the underlying stream 
doesn't
support reset/rewind or similar, the read byte is "lost". As the 
PushbackInputStream
isn't returned from that method and so there's no way to get that byte back.

Not invoking hasEntity() in the filter at all and just taking the stream and 
reading
(buffered) from it, fixes the problem.

It would be great if someone from the CXF team could take a peek at it :).

Thanks!
Veit

Reply via email to