HttpClient throws TruncatedChunkException accessing large chunked resource

17,289

OK, I found out what I'd done. I'd cleaned up my connection too early - basically the boilerplate in my connection method had a

finally
{
    client.getConnectionManager().shutdown();
}

but the method returned the stream object, so reading wasn't completed when the shutdown occurred.

Share:
17,289

Related videos on Youtube

Phasmal
Author by

Phasmal

Updated on June 04, 2022

Comments

  • Phasmal
    Phasmal almost 2 years

    [using httpcore 4.1.4, httpclient 4.2.5, Oracle JDK 1.7.0_25]

    I'm trying to 'proxy' a connection to a third party web service on behalf of a webapp's javascript (AJAX) code and it seems to fail on large chunked responses, erroring part way through a chunk by sending multiple RSTs and throwing a org.apache.http.TruncatedChunkException.

    So I'm wondering:

    1. why is http client trying to drop the connection?
    2. is it doing something sensible? (ie. is the server possibly at fault) or is there something buggy going on here?

    My basic approach is to copy everything from a servlet's request object to an apache components httpclient request and execute. More specfically, I:

    1. create an apache commons httpclient DefaultHttpClient object,
    2. copy all request headers across to a new request object,
    3. set (/override) the host header on the new request with the host/port I'm proxying to,
    4. copy all HTTP parameters to the new request,
    5. copy any entity body across to the new request,
    6. execute the request,
    7. copy response headers to my servlet's response headers, and
    8. copy any entity body as a stream across to the servlet's output stream.

    The bit that is causing me issues is the last one. It seems to fail half way through a chunk and I get the following stacktrace:

    org.apache.http.TruncatedChunkException: Truncated chunk ( expected size: 7752; actual size: 4077)
    at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:186)
    at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:138)
    at <mypackage>.<MyServlet>.service(<MyServlet>.java:XXX)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.jboss.resteasy.plugins.server.servlet.FilterDispatcher.doFilter(FilterDispatcher.java:63)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:724)
    

    I've snooped it with Wireshark and get a process something like this:

    source  dest    info
    client  server  [SYN] seq=0
    server  client  [SYN, ACK] seq=0 ack=1
    client  server  [ACK] seq=1 ack=1
    client  server  GET /url?param=value... HTTP/1.1
    server  client  [ACK] seq=1 ack=221
    server  client  [TCP segment of a reassembled PDU]
    client  server  [ACK] seq=221 ack=4345
    client  server  [FIN, ACK] seq=221 ack=4345
    server  client  [TCP segment of a reassembled PDU]
    client  server  [RST] seq=221
    server  client  Continuation or non-HTTP traffic
    client  server  [RST] seq=221
    

    In my limited understanding, FIN means 'I'm done sending', which IMO is fair enough since the client headers are already sent. However RST/reset seems to just attempt to drop the connection.

    The HTTP headers for client are:

    GET /some/path?params=values HTTP/1.1
    connection: Keep-Alive
    host: target.host.com
    accept: */*
    user-agent: Wget/1.14 (linux-gnu)
    

    And for the server:

    HTTP/1.1 200 OK
    Date: Mon, 16 Sep 2013 03:59:37 GMT
    Server: Apache-Coyote/1.1
    Content-Disposition: inline; filename=geoserver-GetFeature.text
    Content-Type: text/xml; subtype=gml/2.1.2
    Vary: Accept-Encoding
    Connection: close
    Transfer-Encoding: chunked
    

    btw, this question: [restlet ]TruncatedChunkException: looks similar, but doesn't seem to have any helpful info.

    Update: I've tried with a non-chunked site (/. :-) ) and it fails similarly with a:

    org.apache.http.ConnectionClosedException: Premature end of Content-Length delimited message body
    
  • Amit Sadafule
    Amit Sadafule about 7 years
    Then how did you release the connection?
  • Phasmal
    Phasmal about 7 years
    Sorry, this was so long ago I don't remember! I suspect I would have added an explicit close after waiting on the result.