summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/http/client.py4
-rw-r--r--Lib/test/test_httplib.py16
-rw-r--r--Misc/NEWS.d/next/Library/2023-12-16-01-10-47.gh-issue-113199.oDjnjL.rst3
3 files changed, 21 insertions, 2 deletions
diff --git a/Lib/http/client.py b/Lib/http/client.py
index 7bb5d82..5eebfcc 100644
--- a/Lib/http/client.py
+++ b/Lib/http/client.py
@@ -665,6 +665,8 @@ class HTTPResponse(io.BufferedIOBase):
self._close_conn()
elif self.length is not None:
self.length -= len(result)
+ if not self.length:
+ self._close_conn()
return result
def peek(self, n=-1):
@@ -689,6 +691,8 @@ class HTTPResponse(io.BufferedIOBase):
self._close_conn()
elif self.length is not None:
self.length -= len(result)
+ if not self.length:
+ self._close_conn()
return result
def _read1_chunked(self, n):
diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
index caa4c76..089bf5b 100644
--- a/Lib/test/test_httplib.py
+++ b/Lib/test/test_httplib.py
@@ -1546,11 +1546,14 @@ class ExtendedReadTest(TestCase):
resp = self.resp
self._verify_readline(self.resp.readline, self.lines_expected)
- def _verify_readline(self, readline, expected):
+ def test_readline_without_limit(self):
+ self._verify_readline(self.resp.readline, self.lines_expected, limit=-1)
+
+ def _verify_readline(self, readline, expected, limit=5):
all = []
while True:
# short readlines
- line = readline(5)
+ line = readline(limit)
if line and line != b"foo":
if len(line) < 5:
self.assertTrue(line.endswith(b"\n"))
@@ -1558,6 +1561,7 @@ class ExtendedReadTest(TestCase):
if not line:
break
self.assertEqual(b"".join(all), expected)
+ self.assertTrue(self.resp.isclosed())
def test_read1(self):
resp = self.resp
@@ -1577,6 +1581,7 @@ class ExtendedReadTest(TestCase):
break
all.append(data)
self.assertEqual(b"".join(all), self.lines_expected)
+ self.assertTrue(resp.isclosed())
def test_read1_bounded(self):
resp = self.resp
@@ -1588,15 +1593,22 @@ class ExtendedReadTest(TestCase):
self.assertLessEqual(len(data), 10)
all.append(data)
self.assertEqual(b"".join(all), self.lines_expected)
+ self.assertTrue(resp.isclosed())
def test_read1_0(self):
self.assertEqual(self.resp.read1(0), b"")
+ self.assertFalse(self.resp.isclosed())
def test_peek_0(self):
p = self.resp.peek(0)
self.assertLessEqual(0, len(p))
+class ExtendedReadTestContentLengthKnown(ExtendedReadTest):
+ _header, _body = ExtendedReadTest.lines.split('\r\n\r\n', 1)
+ lines = _header + f'\r\nContent-Length: {len(_body)}\r\n\r\n' + _body
+
+
class ExtendedReadTestChunked(ExtendedReadTest):
"""
Test peek(), read1(), readline() in chunked mode
diff --git a/Misc/NEWS.d/next/Library/2023-12-16-01-10-47.gh-issue-113199.oDjnjL.rst b/Misc/NEWS.d/next/Library/2023-12-16-01-10-47.gh-issue-113199.oDjnjL.rst
new file mode 100644
index 0000000..d8e0b17
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-12-16-01-10-47.gh-issue-113199.oDjnjL.rst
@@ -0,0 +1,3 @@
+Make ``http.client.HTTPResponse.read1`` and
+``http.client.HTTPResponse.readline`` close IO after reading all data when
+content length is known. Patch by Illia Volochii.