Skip to content

Commit 26b43e1

Browse files
committed
Handle a case with a not reached newline
1 parent 33f7d77 commit 26b43e1

File tree

3 files changed

+39
-4
lines changed

3 files changed

+39
-4
lines changed

Lib/http/client.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,9 @@ def readline(self, limit=-1):
699699
self.length -= len(result)
700700
if not self.length:
701701
self._close_conn()
702+
elif len(result) != limit and not result.endswith(b"\n"):
703+
self._close_conn()
704+
raise IncompleteRead(result)
702705
return result
703706

704707
def _read1_chunked(self, n):

Lib/test/test_httplib.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1675,9 +1675,40 @@ def test_read_incomplete_read(self):
16751675
def test_read1_incomplete_read(self):
16761676
self._test_incomplete_read(self.resp.read1, expected_none=True)
16771677

1678-
def test_readline_incomplete_read(self):
1678+
def test_readline_incomplete_read_with_complete_line(self):
1679+
"""
1680+
Test that IncompleteRead is raised when readline finishes
1681+
reading a response but the needed content length is not reached.
1682+
"""
1683+
resp = self.resp
1684+
content = resp.fp.read()
1685+
# For this test case, we must ensure that the last byte read
1686+
# will be a newline. There is a different handling of readline
1687+
# not reaching a newline.
1688+
content = content[:-1] + b"\n"
1689+
resp.fp = io.BytesIO(content)
16791690
self._test_incomplete_read(self.resp.readline, expected_none=True)
16801691

1692+
def test_readline_incomplete_read_with_incomplete_line(self):
1693+
"""
1694+
Test that IncompleteRead is raised when readline is expected
1695+
to read a line fully but a newline is not reached.
1696+
"""
1697+
resp = self.resp
1698+
content = resp.fp.read()
1699+
# Truncate the content to the last newline.
1700+
content = content[:content.rindex(b"\n") - 1]
1701+
resp.fp = io.BytesIO(content)
1702+
with self.assertRaises(client.IncompleteRead) as cm:
1703+
while True:
1704+
data = resp.readline()
1705+
if not data:
1706+
break
1707+
exception = cm.exception
1708+
self.assertEqual(exception.partial, content.split(b"\n")[-1])
1709+
self.assertIsNone(exception.expected)
1710+
self.assertTrue(resp.isclosed())
1711+
16811712

16821713
class ExtendedReadTestChunked(ExtendedReadTest):
16831714
"""
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Make ``http.client.HTTPResponse.read1`` and
2-
``http.client.HTTPResponse.readline`` raise :exc:`IncompleteRead` instead of
3-
returning zero bytes if a connection is closed before an expected number of
4-
bytes has been read. Patch by Illia Volochii.
2+
``http.client.HTTPResponse.readline`` raise :exc:`http.client.IncompleteRead`
3+
instead of returning zero bytes if a connection is closed before an expected
4+
number of bytes has been read. Also, ``http.client.HTTPResponse.readline``
5+
raises when an expected newline has not been reached. Patch by Illia Volochii.

0 commit comments

Comments
 (0)