Issue #16723: httplib.HTTPResponse no longer marked closed when the connection
is automatically closed.
This commit is contained in:
parent
f581b37200
commit
b5b9c8cd40
|
@ -324,7 +324,7 @@ class HTTPResponse(io.RawIOBase):
|
|||
# empty version will cause next test to fail.
|
||||
version = ""
|
||||
if not version.startswith("HTTP/"):
|
||||
self.close()
|
||||
self._close_conn()
|
||||
raise BadStatusLine(line)
|
||||
|
||||
# The status code is a three-digit number
|
||||
|
@ -446,22 +446,25 @@ class HTTPResponse(io.RawIOBase):
|
|||
# otherwise, assume it will close
|
||||
return True
|
||||
|
||||
def _close_conn(self):
|
||||
fp = self.fp
|
||||
self.fp = None
|
||||
fp.close()
|
||||
|
||||
def close(self):
|
||||
super().close() # set "closed" flag
|
||||
if self.fp:
|
||||
self.fp.close()
|
||||
self.fp = None
|
||||
self._close_conn()
|
||||
|
||||
# These implementations are for the benefit of io.BufferedReader.
|
||||
|
||||
# XXX This class should probably be revised to act more like
|
||||
# the "raw stream" that BufferedReader expects.
|
||||
|
||||
@property
|
||||
def closed(self):
|
||||
return self.isclosed()
|
||||
|
||||
def flush(self):
|
||||
self.fp.flush()
|
||||
super().flush()
|
||||
if self.fp:
|
||||
self.fp.flush()
|
||||
|
||||
def readable(self):
|
||||
return True
|
||||
|
@ -469,6 +472,7 @@ class HTTPResponse(io.RawIOBase):
|
|||
# End of "raw stream" methods
|
||||
|
||||
def isclosed(self):
|
||||
"""True if the connection is closed."""
|
||||
# NOTE: it is possible that we will not ever call self.close(). This
|
||||
# case occurs when will_close is TRUE, length is None, and we
|
||||
# read up to the last byte, but NOT past it.
|
||||
|
@ -482,7 +486,7 @@ class HTTPResponse(io.RawIOBase):
|
|||
return b""
|
||||
|
||||
if self._method == "HEAD":
|
||||
self.close()
|
||||
self._close_conn()
|
||||
return b""
|
||||
|
||||
if self.chunked:
|
||||
|
@ -496,10 +500,10 @@ class HTTPResponse(io.RawIOBase):
|
|||
try:
|
||||
s = self._safe_read(self.length)
|
||||
except IncompleteRead:
|
||||
self.close()
|
||||
self._close_conn()
|
||||
raise
|
||||
self.length = 0
|
||||
self.close() # we read everything
|
||||
self._close_conn() # we read everything
|
||||
return s
|
||||
|
||||
if self.length is not None:
|
||||
|
@ -514,11 +518,11 @@ class HTTPResponse(io.RawIOBase):
|
|||
if not s:
|
||||
# Ideally, we would raise IncompleteRead if the content-length
|
||||
# wasn't satisfied, but it might break compatibility.
|
||||
self.close()
|
||||
self._close_conn()
|
||||
elif self.length is not None:
|
||||
self.length -= len(s)
|
||||
if not self.length:
|
||||
self.close()
|
||||
self._close_conn()
|
||||
|
||||
return s
|
||||
|
||||
|
@ -539,7 +543,7 @@ class HTTPResponse(io.RawIOBase):
|
|||
except ValueError:
|
||||
# close the connection as protocol synchronisation is
|
||||
# probably lost
|
||||
self.close()
|
||||
self._close_conn()
|
||||
raise IncompleteRead(b''.join(value))
|
||||
if chunk_left == 0:
|
||||
break
|
||||
|
@ -576,7 +580,7 @@ class HTTPResponse(io.RawIOBase):
|
|||
break
|
||||
|
||||
# we read everything; close the "file"
|
||||
self.close()
|
||||
self._close_conn()
|
||||
|
||||
return b''.join(value)
|
||||
|
||||
|
|
|
@ -164,6 +164,9 @@ class BasicTest(TestCase):
|
|||
resp.begin()
|
||||
self.assertEqual(resp.read(), b"Text")
|
||||
self.assertTrue(resp.isclosed())
|
||||
self.assertFalse(resp.closed)
|
||||
resp.close()
|
||||
self.assertTrue(resp.closed)
|
||||
|
||||
body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
|
||||
sock = FakeSocket(body)
|
||||
|
@ -185,6 +188,9 @@ class BasicTest(TestCase):
|
|||
self.assertFalse(resp.isclosed())
|
||||
self.assertEqual(resp.read(2), b'xt')
|
||||
self.assertTrue(resp.isclosed())
|
||||
self.assertFalse(resp.closed)
|
||||
resp.close()
|
||||
self.assertTrue(resp.closed)
|
||||
|
||||
def test_partial_reads_no_content_length(self):
|
||||
# when no length is present, the socket should be gracefully closed when
|
||||
|
@ -198,6 +204,9 @@ class BasicTest(TestCase):
|
|||
self.assertEqual(resp.read(2), b'xt')
|
||||
self.assertEqual(resp.read(1), b'')
|
||||
self.assertTrue(resp.isclosed())
|
||||
self.assertFalse(resp.closed)
|
||||
resp.close()
|
||||
self.assertTrue(resp.closed)
|
||||
|
||||
def test_partial_reads_incomplete_body(self):
|
||||
# if the server shuts down the connection before the whole
|
||||
|
@ -211,6 +220,9 @@ class BasicTest(TestCase):
|
|||
self.assertEqual(resp.read(2), b'xt')
|
||||
self.assertEqual(resp.read(1), b'')
|
||||
self.assertTrue(resp.isclosed())
|
||||
self.assertFalse(resp.closed)
|
||||
resp.close()
|
||||
self.assertTrue(resp.closed)
|
||||
|
||||
def test_host_port(self):
|
||||
# Check invalid host_port
|
||||
|
@ -355,6 +367,9 @@ class BasicTest(TestCase):
|
|||
self.assertEqual(resp.status, 200)
|
||||
self.assertEqual(resp.reason, 'OK')
|
||||
self.assertTrue(resp.isclosed())
|
||||
self.assertFalse(resp.closed)
|
||||
resp.close()
|
||||
self.assertTrue(resp.closed)
|
||||
|
||||
def test_negative_content_length(self):
|
||||
sock = FakeSocket(
|
||||
|
@ -430,6 +445,9 @@ class BasicTest(TestCase):
|
|||
resp.begin()
|
||||
self.assertEqual(resp.read(), b'')
|
||||
self.assertTrue(resp.isclosed())
|
||||
self.assertFalse(resp.closed)
|
||||
resp.close()
|
||||
self.assertTrue(resp.closed)
|
||||
|
||||
class OfflineTest(TestCase):
|
||||
def test_responses(self):
|
||||
|
|
Loading…
Reference in New Issue