You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@hc.apache.org by Eric Johnson <er...@tibco.com> on 2002/12/02 17:50:44 UTC
Patch pending on scanning for HTTP 1.1 - attached
I see that over the weekend lots happened on the mailing list. I guess
that one cannot safely go on vacation around here!
I've seen a few posts about problems with connections closing
unexpectedly. I had this problem, and traced it down to several issues.
The problem stems from the wrappers around the input streams that would
occassionally close or not close the underlying socket, in ways that
were unexpected. There seems to be an odd expectation that the "close"
function would never be called on the various InputStream variants,
except by HttpClient and its associate classes.
I've attached the patch that I have, but I don't expect it to actually
be applied yet - as I have mentioned before, I think it prudent to wait
for the far more important HttpClient/HttpMultiClient merge. So here it
is - I'll resubmit after I see the big merge in CVS.
-Eric.
The patch consists of the following:
* AutoCloseInputStream now does not call "super.read()" once close
has been called on the connection itself. The close() function is
now implemented to close the underlying _connection_ rather than
just the socket input stream. Failing to close the connection
would cause an unnecessary (and sometimes troublesome) recoverable
exception with subsequent requests.
* ChunkedInputStream does not close the underlying stream anymore.
It does, however, "exhaust" the remaining chunked stream when the
"close()" method is called, eliminating _almost_ all of the need
for HttpClient to scan for HTTP/1.1 lines (which is error prone,
due to the unpredictability of the content of the underlying
responses). The "read" methods check to see if the connection is
closed and throw an exception.
* ContentLengthInputStream - similar changes to that of
ChunkedInputStream.
* The HeadMethod now calls shouldCloseConnection and
connection.close() as appropriate.
* HttpClient.executeMethod() now calls InputStream.close() on the
previous response's input stream (this is part that may be tricky
to carry over to the MultiClient merge). In this way, a client of
a "Get" method, for example, need not actually read the entire
response - calling close has the effect of doing so, or closing
the underlying connection, as appropriate.
* HttpConnection - now keeps track of the InputStream for the last
executeMethod() request.
* HttpMethodBase - Now keeps track of the number of "recoverable
exceptions" - so that I could write test cases that monitor
whether recoverable exceptions are being thrown when they
shouldn't be! Also calls "close" on the input stream when done
reading it, and sets the connection's last response input stream.
* TestGetMethodLocal - added an additional test where the "GET"
method response body is never read, but is followed immediately by
another GET request.
* TestHttpClientLocalHost - now does "GET" requests from
"/httpclienttest/body" (based on system props), rather than "/" as
the root of the server is not controlled by the standard WAR file.
I was getting 302 responses, and thus test failures, until I
pointed to the new location.
* TestMethodsLocalHost - same as TestHttpClientLocalHost
* TestMethodsNoHost - added new tests of the HeadMethod.
Miscellaneous random notes:
* I ran into my difficulties initially because I was using Tomcat
4.1.10 with the old (now deprecated) HttpConnector (1.1
compliant). It turns out that it returns a "Connection: close"
header on any request that fails to indicate content length either
via a content-length header or a chunked encoding. This sounds
similar to someone else's posting about difficulties with the
"Connection: close" header.
* I had subsequent difficulties due to sending the results of a GET
request to Xerces for XML parsing. Xerces would eventually call
"close" on the stream passed to it. This would have the
unfortunate effect, when working with ContentLengthInputStream for
example, of closing the underlying socket - without notifying the
connection. Now, the close changes the state of the
ContentLengthInputStream (by exhausting the input stream), but
does not close the socket. Of course, if the AutoCloseInputStream
wrapper gets used, the connection will be closed....
Enjoy. Please let me know of any feedback you might have, I will be
happy to take another shot at revising.
-Eric.