Skip to content

gh-115997: Make HTTPResponse.read1 and readline raise IncompleteRead #115998

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Next Next commit
gh-115997: Make HTTPResponse.read1 and readline raise `Incomplete…
…Read`
  • Loading branch information
illia-v committed Feb 27, 2024
commit 9878730e20d68eb2a04ed82c5fffff9ab8f94d02
4 changes: 4 additions & 0 deletions Lib/http/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,8 @@ def read1(self, n=-1):
result = self.fp.read1(n)
if not result and n:
self._close_conn()
if self.length:
raise IncompleteRead(result, self.length)
elif self.length is not None:
self.length -= len(result)
if not self.length:
Expand All @@ -689,6 +691,8 @@ def readline(self, limit=-1):
result = self.fp.readline(limit)
if not result and limit:
self._close_conn()
if self.length:
raise IncompleteRead(result, self.length)
elif self.length is not None:
self.length -= len(result)
if not self.length:
Expand Down
24 changes: 24 additions & 0 deletions Lib/test/test_httplib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1608,6 +1608,30 @@ 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

def _test_incomplete_read(self, read_meth):
resp = self.resp
# Reduce the size of content the response object will read to
# cause the incomplete read.
resp.fp.read(1)
with self.assertRaises(client.IncompleteRead) as cm:
while True:
data = resp.read1()
if not data:
break
exception = cm.exception
self.assertEqual(exception.partial, b"")
self.assertEqual(exception.expected, 1)
self.assertTrue(resp.isclosed())

def test_read_incomplete_read(self):
self._test_incomplete_read(self.resp.read)

def test_read1_incomplete_read(self):
self._test_incomplete_read(self.resp.read1)

def test_readline_incomplete_read(self):
self._test_incomplete_read(self.resp.readline)


class ExtendedReadTestChunked(ExtendedReadTest):
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Make ``http.client.HTTPResponse.read1`` and
``http.client.HTTPResponse.readline`` raise :exc:`IncompleteRead` instead of
returning zero bytes if a connection is closed before an expected number of
bytes has been read. Patch by Illia Volochii.