mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
Issue #13713: fix a regression in HTTP chunked reading after 806cfe39f729
(originally issue #13464: Add a readinto() method to http.client.HTTPResponse)
This commit is contained in:
parent
d710d147f6
commit
f7e7818e24
2 changed files with 51 additions and 17 deletions
|
@ -603,12 +603,12 @@ class HTTPResponse(io.RawIOBase):
|
||||||
if len(mvb) < chunk_left:
|
if len(mvb) < chunk_left:
|
||||||
n = self._safe_readinto(mvb)
|
n = self._safe_readinto(mvb)
|
||||||
self.chunk_left = chunk_left - n
|
self.chunk_left = chunk_left - n
|
||||||
return n
|
return total_bytes + n
|
||||||
elif len(mvb) == chunk_left:
|
elif len(mvb) == chunk_left:
|
||||||
n = self._safe_readinto(mvb)
|
n = self._safe_readinto(mvb)
|
||||||
self._safe_read(2) # toss the CRLF at the end of the chunk
|
self._safe_read(2) # toss the CRLF at the end of the chunk
|
||||||
self.chunk_left = None
|
self.chunk_left = None
|
||||||
return n
|
return total_bytes + n
|
||||||
else:
|
else:
|
||||||
temp_mvb = mvb[0:chunk_left]
|
temp_mvb = mvb[0:chunk_left]
|
||||||
n = self._safe_readinto(temp_mvb)
|
n = self._safe_readinto(temp_mvb)
|
||||||
|
|
|
@ -293,15 +293,28 @@ class BasicTest(TestCase):
|
||||||
'Transfer-Encoding: chunked\r\n\r\n'
|
'Transfer-Encoding: chunked\r\n\r\n'
|
||||||
'a\r\n'
|
'a\r\n'
|
||||||
'hello worl\r\n'
|
'hello worl\r\n'
|
||||||
'1\r\n'
|
'3\r\n'
|
||||||
'd\r\n'
|
'd! \r\n'
|
||||||
|
'8\r\n'
|
||||||
|
'and now \r\n'
|
||||||
|
'22\r\n'
|
||||||
|
'for something completely different\r\n'
|
||||||
)
|
)
|
||||||
|
expected = b'hello world! and now for something completely different'
|
||||||
sock = FakeSocket(chunked_start + '0\r\n')
|
sock = FakeSocket(chunked_start + '0\r\n')
|
||||||
resp = client.HTTPResponse(sock, method="GET")
|
resp = client.HTTPResponse(sock, method="GET")
|
||||||
resp.begin()
|
resp.begin()
|
||||||
self.assertEqual(resp.read(), b'hello world')
|
self.assertEqual(resp.read(), expected)
|
||||||
resp.close()
|
resp.close()
|
||||||
|
|
||||||
|
# Various read sizes
|
||||||
|
for n in range(1, 12):
|
||||||
|
sock = FakeSocket(chunked_start + '0\r\n')
|
||||||
|
resp = client.HTTPResponse(sock, method="GET")
|
||||||
|
resp.begin()
|
||||||
|
self.assertEqual(resp.read(n) + resp.read(n) + resp.read(), expected)
|
||||||
|
resp.close()
|
||||||
|
|
||||||
for x in ('', 'foo\r\n'):
|
for x in ('', 'foo\r\n'):
|
||||||
sock = FakeSocket(chunked_start + x)
|
sock = FakeSocket(chunked_start + x)
|
||||||
resp = client.HTTPResponse(sock, method="GET")
|
resp = client.HTTPResponse(sock, method="GET")
|
||||||
|
@ -309,9 +322,10 @@ class BasicTest(TestCase):
|
||||||
try:
|
try:
|
||||||
resp.read()
|
resp.read()
|
||||||
except client.IncompleteRead as i:
|
except client.IncompleteRead as i:
|
||||||
self.assertEqual(i.partial, b'hello world')
|
self.assertEqual(i.partial, expected)
|
||||||
self.assertEqual(repr(i),'IncompleteRead(11 bytes read)')
|
expected_message = 'IncompleteRead(%d bytes read)' % len(expected)
|
||||||
self.assertEqual(str(i),'IncompleteRead(11 bytes read)')
|
self.assertEqual(repr(i), expected_message)
|
||||||
|
self.assertEqual(str(i), expected_message)
|
||||||
else:
|
else:
|
||||||
self.fail('IncompleteRead expected')
|
self.fail('IncompleteRead expected')
|
||||||
finally:
|
finally:
|
||||||
|
@ -323,29 +337,49 @@ class BasicTest(TestCase):
|
||||||
'Transfer-Encoding: chunked\r\n\r\n'
|
'Transfer-Encoding: chunked\r\n\r\n'
|
||||||
'a\r\n'
|
'a\r\n'
|
||||||
'hello worl\r\n'
|
'hello worl\r\n'
|
||||||
'1\r\n'
|
'3\r\n'
|
||||||
'd\r\n'
|
'd! \r\n'
|
||||||
|
'8\r\n'
|
||||||
|
'and now \r\n'
|
||||||
|
'22\r\n'
|
||||||
|
'for something completely different\r\n'
|
||||||
)
|
)
|
||||||
|
expected = b'hello world! and now for something completely different'
|
||||||
|
nexpected = len(expected)
|
||||||
|
b = bytearray(128)
|
||||||
|
|
||||||
sock = FakeSocket(chunked_start + '0\r\n')
|
sock = FakeSocket(chunked_start + '0\r\n')
|
||||||
resp = client.HTTPResponse(sock, method="GET")
|
resp = client.HTTPResponse(sock, method="GET")
|
||||||
resp.begin()
|
resp.begin()
|
||||||
b = bytearray(16)
|
|
||||||
n = resp.readinto(b)
|
n = resp.readinto(b)
|
||||||
self.assertEqual(b[:11], b'hello world')
|
self.assertEqual(b[:nexpected], expected)
|
||||||
self.assertEqual(n, 11)
|
self.assertEqual(n, nexpected)
|
||||||
resp.close()
|
resp.close()
|
||||||
|
|
||||||
|
# Various read sizes
|
||||||
|
for n in range(1, 12):
|
||||||
|
sock = FakeSocket(chunked_start + '0\r\n')
|
||||||
|
resp = client.HTTPResponse(sock, method="GET")
|
||||||
|
resp.begin()
|
||||||
|
m = memoryview(b)
|
||||||
|
i = resp.readinto(m[0:n])
|
||||||
|
i += resp.readinto(m[i:n + i])
|
||||||
|
i += resp.readinto(m[i:])
|
||||||
|
self.assertEqual(b[:nexpected], expected)
|
||||||
|
self.assertEqual(i, nexpected)
|
||||||
|
resp.close()
|
||||||
|
|
||||||
for x in ('', 'foo\r\n'):
|
for x in ('', 'foo\r\n'):
|
||||||
sock = FakeSocket(chunked_start + x)
|
sock = FakeSocket(chunked_start + x)
|
||||||
resp = client.HTTPResponse(sock, method="GET")
|
resp = client.HTTPResponse(sock, method="GET")
|
||||||
resp.begin()
|
resp.begin()
|
||||||
try:
|
try:
|
||||||
b = bytearray(16)
|
|
||||||
n = resp.readinto(b)
|
n = resp.readinto(b)
|
||||||
except client.IncompleteRead as i:
|
except client.IncompleteRead as i:
|
||||||
self.assertEqual(i.partial, b'hello world')
|
self.assertEqual(i.partial, expected)
|
||||||
self.assertEqual(repr(i),'IncompleteRead(11 bytes read)')
|
expected_message = 'IncompleteRead(%d bytes read)' % len(expected)
|
||||||
self.assertEqual(str(i),'IncompleteRead(11 bytes read)')
|
self.assertEqual(repr(i), expected_message)
|
||||||
|
self.assertEqual(str(i), expected_message)
|
||||||
else:
|
else:
|
||||||
self.fail('IncompleteRead expected')
|
self.fail('IncompleteRead expected')
|
||||||
finally:
|
finally:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue