diff --git a/Lib/http/client.py b/Lib/http/client.py index 5aa178d7b127d90..9b57128b9b0a525 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -1023,6 +1023,7 @@ def _send_output(self, message_body=None, encode_chunked=False): # is needed to allow the current position of mmap'ed # files to be taken into account. chunks = self._read_readable(message_body) + message_body.seek(0) else: try: # this is solely to check to see if message_body diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py index 77dec0ce713ccb4..4f767ed9555c465 100644 --- a/Lib/test/test_urllib2_localnet.py +++ b/Lib/test/test_urllib2_localnet.py @@ -238,7 +238,29 @@ def do_GET(self): # Request Unauthorized self.do_AUTHHEAD() - + def do_POST(self): + if not self.headers.get("Authorization", ""): + self.do_AUTHHEAD() + self.wfile.write(b"No Auth header received") + elif self.headers.get( + "Authorization", "") == "Basic " + self.ENCODED_AUTH: + encoding = self.headers.get("Transfer-Encoding") + if encoding is None: + length = int(self.headers.get("Content-Length")) + else: + assert encoding == "chunked" + length = int(self.rfile.readline(), 16) + request = self.rfile.read(length) + assert len(request) == length + if length > 0: + self.send_response(200, "OK") + self.end_headers() + self.wfile.write(request) + else: + self.send_response(400, "Empty request data") + self.end_headers() + else: + self.do_AUTHHEAD() # Proxy test infrastructure @@ -314,6 +336,19 @@ def test_basic_auth_httperror(self): urllib.request.install_opener(urllib.request.build_opener(ah)) self.assertRaises(urllib.error.HTTPError, urllib.request.urlopen, self.server_url) + def test_basic_auth_mmap_payload(self): + from mmap import mmap + data = "field=value".encode("ascii") + mem = mmap(-1, len(data)) + mem[:] = data + auth_handler = urllib.request.HTTPBasicAuthHandler() + auth_handler.add_password(realm=self.REALM, uri=self.server_url, + user=self.USER, passwd=self.PASSWD) + opener = urllib.request.build_opener(auth_handler) + urllib.request.install_opener(opener) + response = opener.open(self.server_url, mem) + self.assertEqual(response.read(), data) + class ProxyAuthTests(unittest.TestCase): URL = "http://localhost" @@ -658,7 +693,6 @@ def test_line_iteration(self): (index, len(lines[index]), len(line))) self.assertEqual(index + 1, len(lines)) - threads_key = None def setUpModule(): diff --git a/Misc/NEWS.d/next/Library/2019-02-13-18-51-31.bpo-5038.NWt7FW.rst b/Misc/NEWS.d/next/Library/2019-02-13-18-51-31.bpo-5038.NWt7FW.rst new file mode 100644 index 000000000000000..b291779afc9b521 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-02-13-18-51-31.bpo-5038.NWt7FW.rst @@ -0,0 +1,2 @@ +http lib allows mmap'ed files to be resent when the http server responds with 401 unauthorized or similar initial responses +and the requests has to be resend. \ No newline at end of file