org.apache.http.entityutils#toString() is causing java.io.EOFException in case of chunked transfer-encoding when the payload is empty

Viewed 126

The title of my question very much sums up problem. I will try to provide further details here:

I had enabled the org.apache.http logs and this is the request sent:

 DEBUG Test worker org.apache.http.headers:136 - http-outgoing-1 >> Content-Type: application/x-www-form-urlencoded
 DEBUG Test worker org.apache.http.headers:136 - http-outgoing-1 >> Host: <host-address>
 DEBUG Test worker org.apache.http.headers:136 - http-outgoing-1 >> Connection: Keep-Alive
 DEBUG Test worker org.apache.http.headers:136 - http-outgoing-1 >> User-Agent: Apache-HttpClient/4.5.9 (Java/1.8.0_181)
 DEBUG Test worker org.apache.http.headers:136 - http-outgoing-1 >> Accept-Encoding: gzip,deflate
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 >> "GET /data/RestEndPoint('<unique-id>') HTTP/1.1[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 >> "Authorization: Bearer <Bearer-Token>[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 >> "Content-Type: application/x-www-form-urlencoded[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 >> "Host: trial-<Host-address>[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 >> "Connection: Keep-Alive[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 >> "User-Agent: Apache-HttpClient/4.5.9 (Java/1.8.0_181)[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 >> "Accept-Encoding: gzip,deflate[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 >> "[\r][\n]"

I get a valid response from the resource endpoint (in this cases, it is expected to get HTTP : 404 ) Here is the response from the server/ endpoint

 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 << "HTTP/1.1 404 Not Found[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 << "Transfer-Encoding: chunked[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 << "Content-Encoding: gzip[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 << "Strict-Transport-Security: max-age=31536000; includeSubDomains[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 << "X-Content-Type-Options: nosniff[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 << "X-Frame-Options: SAMEORIGIN[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 << "X-ServiceFabric: ResourceNotFound[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 << "X-Powered-By: ARR/3.0[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 << "Request-Context: appId=cid-v1:47532108-1d6f-4e03-9925-5a529abc43fe[\r][\n]"
 
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 << "[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 << "0[\r][\n]"
 DEBUG Test worker org.apache.http.wire:73 - http-outgoing-1 << "[\r][\n]"
 DEBUG Test worker org.apache.http.headers:122 - http-outgoing-1 << HTTP/1.1 404 Not Found
 DEBUG Test worker org.apache.http.headers:125 - http-outgoing-1 << Transfer-Encoding: chunked
 DEBUG Test worker org.apache.http.headers:125 - http-outgoing-1 << Content-Encoding: gzip
 DEBUG Test worker org.apache.http.headers:125 - http-outgoing-1 << Strict-Transport-Security: max-age=31536000; includeSubDomains
 DEBUG Test worker org.apache.http.headers:125 - http-outgoing-1 << X-Content-Type-Options: nosniff
 DEBUG Test worker org.apache.http.headers:125 - http-outgoing-1 << X-Frame-Options: SAMEORIGIN
 
 DEBUG Test worker org.apache.http.headers:125 - http-outgoing-1 << X-ServiceFabric: ResourceNotFound
 DEBUG Test worker org.apache.http.headers:125 - http-outgoing-1 << X-Powered-By: ARR/3.0
 
 

Uptil now everything works fine, but the following block of code is throwing an exception:

HttpEntity entity = response.getEntity();

Arrays.stream(response.getAllHeaders())
      .forEach(head -> responseHeaders.put(head.getName(),
                        head.getValue()));

responseEntity = (null != entity)
                ? EntityUtils.toString(entity, HttpConfigConstants.UTF8)
                : null;

The line EntityUtils.toString(entity, HttpConfigConstants.UTF8) is throwing following exception:

 java.io.EOFException
        at java.util.zip.GZIPInputStream.readUByte(GZIPInputStream.java:268)
        at java.util.zip.GZIPInputStream.readUShort(GZIPInputStream.java:258)
        at java.util.zip.GZIPInputStream.readHeader(GZIPInputStream.java:164)
        at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:79)
        at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:91)
        at org.apache.http.client.entity.GZIPInputStreamFactory.create(GZIPInputStreamFactory.java:61)
        at org.apache.http.client.entity.LazyDecompressingInputStream.initWrapper(LazyDecompressingInputStream.java:51)
        at org.apache.http.client.entity.LazyDecompressingInputStream.read(LazyDecompressingInputStream.java:69)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.Reader.read(Reader.java:140)
        at org.apache.http.util.EntityUtils.toString(EntityUtils.java:227)
        at org.apache.http.util.EntityUtils.toString(EntityUtils.java:270)
        at org.apache.http.util.EntityUtils.toString(EntityUtils.java:290)

Isn't the EntityUtils class checking for empty stream? Is there a bug in EntityUtils or what should I check prior to calling the EntityUtils.toString(entity, HttpConfigConstants.UTF8) so that geniune EOF exceptions are not masked and avoid unnecessary EOF exceptions during valid responses?


NOTE: The same EOFexception would be thrown in case of success http response codes as well that won't have payload for ex: 201 (resource created: POST) 204 (resource updated: PATCH)

How should I avoid these?

0 Answers
Related