From 031148e3720d6c41f42e6647dd17f321ecf5a8b1 Mon Sep 17 00:00:00 2001 From: liwenjun Date: Wed, 5 Jun 2024 10:30:16 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E4=B8=81=EF=BC=9Agithub=20issue#3206?= =?UTF-8?q?=E3=80=81issue#3271?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/urllib3/connection.py | 3 +- test/with_dummyserver/test_socketlevel.py | 86 +++++++++++------------ 2 files changed, 42 insertions(+), 47 deletions(-) diff --git a/src/urllib3/connection.py b/src/urllib3/connection.py index 4a71225..4a67b5e 100644 --- a/src/urllib3/connection.py +++ b/src/urllib3/connection.py @@ -73,7 +73,7 @@ port_by_scheme = {"http": 80, "https": 443} # When it comes time to update this value as a part of regular maintenance # (ie test_recent_date is failing) update it to ~6 months before the current date. -RECENT_DATE = datetime.date(2022, 1, 1) +RECENT_DATE = datetime.date(2024, 6, 1) _CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]") @@ -865,6 +865,7 @@ def _wrap_proxy_error(err: Exception, proxy_scheme: str | None) -> ProxyError: is_likely_http_proxy = ( "wrong version number" in error_normalized or "unknown protocol" in error_normalized + or "record layer failure" in error_normalized ) http_proxy_warning = ( ". Your proxy appears to only use HTTP and not HTTPS, " diff --git a/test/with_dummyserver/test_socketlevel.py b/test/with_dummyserver/test_socketlevel.py index 32bf5e2..76cb760 100644 --- a/test/with_dummyserver/test_socketlevel.py +++ b/test/with_dummyserver/test_socketlevel.py @@ -12,7 +12,6 @@ import shutil import socket import ssl import tempfile -import time import typing import zlib from collections import OrderedDict @@ -1311,7 +1310,8 @@ class TestSSL(SocketDummyServerTestCase): self._start_server(socket_handler) with HTTPSConnectionPool(self.host, self.port, ca_certs=DEFAULT_CA) as pool: with pytest.raises( - SSLError, match=r"(wrong version number|record overflow)" + SSLError, + match=r"(wrong version number|record overflow|record layer failure)", ): pool.request("GET", "/", retries=False) @@ -1826,11 +1826,14 @@ class TestHeaders(SocketDummyServerTestCase): body: None | bytes | io.BytesIO if body_type is None: body = None + expected = b"\r\n\r\n" elif body_type == "bytes": body = b"my-body" + expected = b"\r\n\r\nmy-body" elif body_type == "bytes-io": body = io.BytesIO(b"bytes-io-body") body.seek(0, 0) + expected = b"bytes-io-body\r\n0\r\n\r\n" else: raise ValueError("Unknonw body type") @@ -1841,12 +1844,9 @@ class TestHeaders(SocketDummyServerTestCase): sock = listener.accept()[0] sock.settimeout(0) - start = time.time() - while time.time() - start < (LONG_TIMEOUT / 2): - try: + while expected not in buffer: + with contextlib.suppress(BlockingIOError): buffer += sock.recv(65536) - except OSError: - continue sock.sendall( b"HTTP/1.1 200 OK\r\n" @@ -2259,18 +2259,16 @@ class TestContentFraming(SocketDummyServerTestCase): self, method: str, chunked: bool, body_type: str ) -> None: buffer = bytearray() + expected_bytes = b"\r\n\r\na\r\nxxxxxxxxxx\r\n0\r\n\r\n" def socket_handler(listener: socket.socket) -> None: nonlocal buffer sock = listener.accept()[0] sock.settimeout(0) - start = time.time() - while time.time() - start < (LONG_TIMEOUT / 2): - try: + while expected_bytes not in buffer: + with contextlib.suppress(BlockingIOError): buffer += sock.recv(65536) - except OSError: - continue sock.sendall( b"HTTP/1.1 200 OK\r\n" @@ -2309,7 +2307,7 @@ class TestContentFraming(SocketDummyServerTestCase): assert b"Transfer-Encoding: chunked\r\n" in sent_bytes assert b"User-Agent: python-urllib3/" in sent_bytes assert b"content-length" not in sent_bytes.lower() - assert b"\r\n\r\na\r\nxxxxxxxxxx\r\n0\r\n\r\n" in sent_bytes + assert expected_bytes in sent_bytes @pytest.mark.parametrize("method", ["POST", "PUT", "PATCH"]) @pytest.mark.parametrize( @@ -2317,29 +2315,9 @@ class TestContentFraming(SocketDummyServerTestCase): ) def test_chunked_not_specified(self, method: str, body_type: str) -> None: buffer = bytearray() - - def socket_handler(listener: socket.socket) -> None: - nonlocal buffer - sock = listener.accept()[0] - sock.settimeout(0) - - start = time.time() - while time.time() - start < (LONG_TIMEOUT / 2): - try: - buffer += sock.recv(65536) - except OSError: - continue - - sock.sendall( - b"HTTP/1.1 200 OK\r\n" - b"Server: example.com\r\n" - b"Content-Length: 0\r\n\r\n" - ) - sock.close() - - self._start_server(socket_handler) - + expected_bytes: bytes body: typing.Any + if body_type == "generator": def body_generator() -> typing.Generator[bytes, None, None]: @@ -2347,25 +2325,44 @@ class TestContentFraming(SocketDummyServerTestCase): body = body_generator() should_be_chunked = True - elif body_type == "file": body = io.BytesIO(b"x" * 10) body.seek(0, 0) should_be_chunked = True - elif body_type == "file_text": body = io.StringIO("x" * 10) body.seek(0, 0) should_be_chunked = True - elif body_type == "bytearray": body = bytearray(b"x" * 10) should_be_chunked = False - else: body = b"x" * 10 should_be_chunked = False + if should_be_chunked: + expected_bytes = b"\r\n\r\na\r\nxxxxxxxxxx\r\n0\r\n\r\n" + else: + expected_bytes = b"\r\n\r\nxxxxxxxxxx" + + def socket_handler(listener: socket.socket) -> None: + nonlocal buffer + sock = listener.accept()[0] + sock.settimeout(0) + + while expected_bytes not in buffer: + with contextlib.suppress(BlockingIOError): + buffer += sock.recv(65536) + + sock.sendall( + b"HTTP/1.1 200 OK\r\n" + b"Server: example.com\r\n" + b"Content-Length: 0\r\n\r\n" + ) + sock.close() + + self._start_server(socket_handler) + with HTTPConnectionPool( self.host, self.port, timeout=LONG_TIMEOUT, retries=False ) as pool: @@ -2381,12 +2378,12 @@ class TestContentFraming(SocketDummyServerTestCase): if should_be_chunked: assert b"content-length" not in sent_bytes.lower() assert b"Transfer-Encoding: chunked\r\n" in sent_bytes - assert b"\r\n\r\na\r\nxxxxxxxxxx\r\n0\r\n\r\n" in sent_bytes + assert expected_bytes in sent_bytes else: assert b"Content-Length: 10\r\n" in sent_bytes assert b"transfer-encoding" not in sent_bytes.lower() - assert sent_bytes.endswith(b"\r\n\r\nxxxxxxxxxx") + assert sent_bytes.endswith(expected_bytes) @pytest.mark.parametrize( "header_transform", @@ -2417,12 +2414,9 @@ class TestContentFraming(SocketDummyServerTestCase): sock = listener.accept()[0] sock.settimeout(0) - start = time.time() - while time.time() - start < (LONG_TIMEOUT / 2): - try: + while expected not in buffer: + with contextlib.suppress(BlockingIOError): buffer += sock.recv(65536) - except OSError: - continue sock.sendall( b"HTTP/1.1 200 OK\r\n" -- Gitee