mirror of
https://github.com/python/cpython.git
synced 2025-10-03 13:45:29 +00:00
[3.9] bpo-42853: Fix http.client fails to download >2GiB data over TLS (GH-27405)
Revert "bpo-36050: optimize HTTPResponse.read() (GH-12698)"
This reverts commit d6bf6f2d0c
.
This commit is contained in:
parent
a13edfb857
commit
153365d864
2 changed files with 33 additions and 10 deletions
|
@ -105,6 +105,9 @@ globals().update(http.HTTPStatus.__members__)
|
||||||
# Mapping status codes to official W3C names
|
# Mapping status codes to official W3C names
|
||||||
responses = {v: v.phrase for v in http.HTTPStatus.__members__.values()}
|
responses = {v: v.phrase for v in http.HTTPStatus.__members__.values()}
|
||||||
|
|
||||||
|
# maximal amount of data to read at one time in _safe_read
|
||||||
|
MAXAMOUNT = 1048576
|
||||||
|
|
||||||
# maximal line length when calling readline().
|
# maximal line length when calling readline().
|
||||||
_MAXLINE = 65536
|
_MAXLINE = 65536
|
||||||
_MAXHEADERS = 100
|
_MAXHEADERS = 100
|
||||||
|
@ -604,24 +607,43 @@ class HTTPResponse(io.BufferedIOBase):
|
||||||
raise IncompleteRead(bytes(b[0:total_bytes]))
|
raise IncompleteRead(bytes(b[0:total_bytes]))
|
||||||
|
|
||||||
def _safe_read(self, amt):
|
def _safe_read(self, amt):
|
||||||
"""Read the number of bytes requested.
|
"""Read the number of bytes requested, compensating for partial reads.
|
||||||
|
|
||||||
|
Normally, we have a blocking socket, but a read() can be interrupted
|
||||||
|
by a signal (resulting in a partial read).
|
||||||
|
|
||||||
|
Note that we cannot distinguish between EOF and an interrupt when zero
|
||||||
|
bytes have been read. IncompleteRead() will be raised in this
|
||||||
|
situation.
|
||||||
|
|
||||||
This function should be used when <amt> bytes "should" be present for
|
This function should be used when <amt> bytes "should" be present for
|
||||||
reading. If the bytes are truly not available (due to EOF), then the
|
reading. If the bytes are truly not available (due to EOF), then the
|
||||||
IncompleteRead exception can be used to detect the problem.
|
IncompleteRead exception can be used to detect the problem.
|
||||||
"""
|
"""
|
||||||
data = self.fp.read(amt)
|
s = []
|
||||||
if len(data) < amt:
|
while amt > 0:
|
||||||
raise IncompleteRead(data, amt-len(data))
|
chunk = self.fp.read(min(amt, MAXAMOUNT))
|
||||||
return data
|
if not chunk:
|
||||||
|
raise IncompleteRead(b''.join(s), amt)
|
||||||
|
s.append(chunk)
|
||||||
|
amt -= len(chunk)
|
||||||
|
return b"".join(s)
|
||||||
|
|
||||||
def _safe_readinto(self, b):
|
def _safe_readinto(self, b):
|
||||||
"""Same as _safe_read, but for reading into a buffer."""
|
"""Same as _safe_read, but for reading into a buffer."""
|
||||||
amt = len(b)
|
total_bytes = 0
|
||||||
n = self.fp.readinto(b)
|
mvb = memoryview(b)
|
||||||
if n < amt:
|
while total_bytes < len(b):
|
||||||
raise IncompleteRead(bytes(b[:n]), amt-n)
|
if MAXAMOUNT < len(mvb):
|
||||||
return n
|
temp_mvb = mvb[0:MAXAMOUNT]
|
||||||
|
n = self.fp.readinto(temp_mvb)
|
||||||
|
else:
|
||||||
|
n = self.fp.readinto(mvb)
|
||||||
|
if not n:
|
||||||
|
raise IncompleteRead(bytes(mvb[0:total_bytes]), len(b))
|
||||||
|
mvb = mvb[n:]
|
||||||
|
total_bytes += n
|
||||||
|
return total_bytes
|
||||||
|
|
||||||
def read1(self, n=-1):
|
def read1(self, n=-1):
|
||||||
"""Read with at most one underlying system call. If at least one
|
"""Read with at most one underlying system call. If at least one
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix ``http.client.HTTPSConnection`` fails to download >2GiB data.
|
Loading…
Add table
Add a link
Reference in a new issue