diff --git a/Lib/http/client.py b/Lib/http/client.py index 5593b39b0e4..392715b24dc 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -681,14 +681,6 @@ class HTTPConnection: default_port = HTTP_PORT auto_open = 1 debuglevel = 0 - # TCP Maximum Segment Size (MSS) is determined by the TCP stack on - # a per-connection basis. There is no simple and efficient - # platform independent mechanism for determining the MSS, so - # instead a reasonable estimate is chosen. The getsockopt() - # interface using the TCP_MAXSEG parameter may be a suitable - # approach on some operating systems. A value of 16KiB is chosen - # as a reasonable estimate of the maximum MSS. - mss = 16384 def __init__(self, host, port=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, source_address=None): @@ -786,8 +778,9 @@ class HTTPConnection: def connect(self): """Connect to the host and port specified in __init__.""" - self.sock = self._create_connection((self.host,self.port), - self.timeout, self.source_address) + self.sock = self._create_connection( + (self.host,self.port), self.timeout, self.source_address) + self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) if self._tunnel_host: self._tunnel() @@ -866,19 +859,9 @@ class HTTPConnection: self._buffer.extend((b"", b"")) msg = b"\r\n".join(self._buffer) del self._buffer[:] - # If msg and message_body are sent in a single send() call, - # it will avoid performance problems caused by the interaction - # between delayed ack and the Nagle algorithm. However, - # there is no performance gain if the message is larger - # than MSS (and there is a memory penalty for the message - # copy). - if isinstance(message_body, bytes) and len(message_body) < self.mss: - msg += message_body - message_body = None + self.send(msg) if message_body is not None: - # message_body was not a string (i.e. it is a file), and - # we must run the risk of Nagle. self.send(message_body) def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0): diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 62612763f06..08efa19d806 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -70,6 +70,9 @@ class FakeSocket: def close(self): pass + def setsockopt(self, level, optname, value): + pass + class EPipeSocket(FakeSocket): def __init__(self, text, pipe_trigger): @@ -658,28 +661,6 @@ class BasicTest(TestCase): resp.close() self.assertTrue(resp.closed) - def test_delayed_ack_opt(self): - # Test that Nagle/delayed_ack optimistaion works correctly. - - # For small payloads, it should coalesce the body with - # headers, resulting in a single sendall() call - conn = client.HTTPConnection('example.com') - sock = FakeSocket(None) - conn.sock = sock - body = b'x' * (conn.mss - 1) - conn.request('POST', '/', body) - self.assertEqual(sock.sendall_calls, 1) - - # For large payloads, it should send the headers and - # then the body, resulting in more than one sendall() - # call - conn = client.HTTPConnection('example.com') - sock = FakeSocket(None) - conn.sock = sock - body = b'x' * conn.mss - conn.request('POST', '/', body) - self.assertGreater(sock.sendall_calls, 1) - def test_error_leak(self): # Test that the socket is not leaked if getresponse() fails conn = client.HTTPConnection('example.com') diff --git a/Misc/NEWS b/Misc/NEWS index 5373f5bca8b..5cd2c61e821 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1308,6 +1308,10 @@ Library - Issue #22733: Fix ffi_prep_args not zero-extending argument values correctly on 64-bit Windows. +- Issue #23302: Default to TCP_NODELAY=1 upon establishing an HTTPConnection. + Removed use of hard-coded MSS as it's an optimization that's no longer needed + with Nagle disabled. + IDLE ----