diff options
author | R David Murray <rdmurray@bitdance.com> | 2015-04-05 23:26:29 (GMT) |
---|---|---|
committer | R David Murray <rdmurray@bitdance.com> | 2015-04-05 23:26:29 (GMT) |
commit | cae7bdb4241b928f9da025dce48ec98f1b63d576 (patch) | |
tree | 9aff2370b4a06f84fda13e48448023cc6506af17 /Lib/http | |
parent | 142bf565b4e095cfdf59dcb07f6480a7368f1d33 (diff) | |
download | cpython-cae7bdb4241b928f9da025dce48ec98f1b63d576.zip cpython-cae7bdb4241b928f9da025dce48ec98f1b63d576.tar.gz cpython-cae7bdb4241b928f9da025dce48ec98f1b63d576.tar.bz2 |
#3566: Clean up handling of remote server disconnects.
This changeset does two things: introduces a new RemoteDisconnected exception
(that subclasses ConnectionResetError and BadStatusLine) so that a remote
server disconnection can be detected by client code (and provides a better
error message for debugging purposes), and ensures that the client socket is
closed if a ConnectionError happens, so that the automatic re-connection code
can work if the application handles the error and continues on.
Tests are added that confirm that a connection is re-used or not re-used
as appropriate to the various combinations of protocol version and headers.
Patch by Martin Panter, reviewed by Demian Brecht. (Tweaked only slightly by
me.)
Diffstat (limited to 'Lib/http')
-rw-r--r-- | Lib/http/client.py | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/Lib/http/client.py b/Lib/http/client.py index f5889ed..ac120e7 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -20,10 +20,12 @@ request. This diagram details these state transitions: | ( putheader() )* endheaders() v Request-sent - | - | response = getresponse() - v - Unread-response [Response-headers-read] + |\_____________________________ + | | getresponse() raises + | response = getresponse() | ConnectionError + v v + Unread-response Idle + [Response-headers-read] |\____________________ | | | response.read() | putrequest() @@ -83,7 +85,8 @@ __all__ = ["HTTPResponse", "HTTPConnection", "UnknownTransferEncoding", "UnimplementedFileMode", "IncompleteRead", "InvalidURL", "ImproperConnectionState", "CannotSendRequest", "CannotSendHeader", "ResponseNotReady", - "BadStatusLine", "LineTooLong", "error", "responses"] + "BadStatusLine", "LineTooLong", "RemoteDisconnected", "error", + "responses"] HTTP_PORT = 80 HTTPS_PORT = 443 @@ -245,7 +248,8 @@ class HTTPResponse(io.BufferedIOBase): if not line: # Presumably, the server closed the connection before # sending a valid response. - raise BadStatusLine(line) + raise RemoteDisconnected("Remote end closed connection without" + " response") try: version, status, reason = line.split(None, 2) except ValueError: @@ -1160,7 +1164,11 @@ class HTTPConnection: response = self.response_class(self.sock, method=self._method) try: - response.begin() + try: + response.begin() + except ConnectionError: + self.close() + raise assert response.will_close != _UNKNOWN self.__state = _CS_IDLE @@ -1292,5 +1300,10 @@ class LineTooLong(HTTPException): HTTPException.__init__(self, "got more than %d bytes when reading %s" % (_MAXLINE, line_type)) +class RemoteDisconnected(ConnectionResetError, BadStatusLine): + def __init__(self, *pos, **kw): + BadStatusLine.__init__(self, "") + ConnectionResetError.__init__(self, *pos, **kw) + # for backwards compatibility error = HTTPException |