From ba100ec358868a06d0ec540cfd1c631c5aaedcf8 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Thu, 26 Aug 2021 17:37:18 -0700 Subject: [PATCH] Appropriately handle urllib3's InvalidHeader exception --- requests/adapters.py | 5 ++++- tests/test_lowlevel.py | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/requests/adapters.py b/requests/adapters.py index fa4d9b3cc9..9b7f92af66 100644 --- a/requests/adapters.py +++ b/requests/adapters.py @@ -19,6 +19,7 @@ from urllib3.exceptions import ClosedPoolError from urllib3.exceptions import ConnectTimeoutError from urllib3.exceptions import HTTPError as _HTTPError +from urllib3.exceptions import InvalidHeader as _InvalidHeader from urllib3.exceptions import MaxRetryError from urllib3.exceptions import NewConnectionError from urllib3.exceptions import ProxyError as _ProxyError @@ -37,7 +38,7 @@ from .cookies import extract_cookies_to_jar from .exceptions import (ConnectionError, ConnectTimeout, ReadTimeout, SSLError, ProxyError, RetryError, InvalidSchema, InvalidProxyURL, - InvalidURL) + InvalidURL, InvalidHeader) from .auth import _basic_auth_str try: @@ -527,6 +528,8 @@ def send(self, request, stream=False, timeout=None, verify=True, cert=None, prox raise SSLError(e, request=request) elif isinstance(e, ReadTimeoutError): raise ReadTimeout(e, request=request) + elif isinstance(e, _InvalidHeader): + raise InvalidHeader(e, request=request) else: raise diff --git a/tests/test_lowlevel.py b/tests/test_lowlevel.py index d0fa136a69..88ecf9aa38 100644 --- a/tests/test_lowlevel.py +++ b/tests/test_lowlevel.py @@ -46,6 +46,33 @@ def incomplete_chunked_response_handler(sock): close_server.set() # release server block +def test_conflicting_content_lengths(): + """Ensure we correctly throw an InvalidHeader error if multiple + conflicting Content-Length headers are returned. + """ + + def multiple_content_length_response_handler(sock): + request_content = consume_socket_content(sock, timeout=0.5) + + # The server never ends the request and doesn't provide any valid chunks + sock.send(b"HTTP/1.1 200 OK\r\n" + + b"Content-Type: text/plain\r\n" + + b"Content-Length: 16\r\n" + + b"Content-Length: 32\r\n\r\n" + + b"-- Bad Actor -- Original Content\r\n") + + return request_content + + close_server = threading.Event() + server = Server(multiple_content_length_response_handler) + + with server as (host, port): + url = 'http://{}:{}/'.format(host, port) + with pytest.raises(requests.exceptions.InvalidHeader): + r = requests.get(url) + close_server.set() + + def test_digestauth_401_count_reset_on_redirect(): """Ensure we correctly reset num_401_calls after a successful digest auth, followed by a 302 redirect to another digest auth prompt.