mirror of
https://github.com/python/cpython.git
synced 2025-10-09 16:34:44 +00:00
#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.)
This commit is contained in:
parent
142bf565b4
commit
cae7bdb424
4 changed files with 131 additions and 10 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue