diff --git a/src/requests/adapters.py b/src/requests/adapters.py index 670c92767c..4c994fcb1e 100644 --- a/src/requests/adapters.py +++ b/src/requests/adapters.py @@ -40,6 +40,7 @@ InvalidURL, ProxyError, ReadTimeout, + RequestException, RetryError, SSLError, ) @@ -682,15 +683,15 @@ def send( except _ProxyError as e: raise ProxyError(e) - except (_SSLError, _HTTPError) as e: - if isinstance(e, _SSLError): + except (_SSLError, _HTTPError) as err: + if isinstance(err, _SSLError): # This branch is for urllib3 versions earlier than v1.22 - raise SSLError(e, request=request) - elif isinstance(e, ReadTimeoutError): - raise ReadTimeout(e, request=request) - elif isinstance(e, _InvalidHeader): - raise InvalidHeader(e, request=request) + raise SSLError(err, request=request) from err + elif isinstance(err, ReadTimeoutError): + raise ReadTimeout(err, request=request) from err + elif isinstance(err, _InvalidHeader): + raise InvalidHeader(err, request=request) from err else: - raise + raise RequestException(err, request=request) from err return self.build_response(request, resp) diff --git a/tests/test_adapters.py b/tests/test_adapters.py index 6c55d5a130..fdda8418d9 100644 --- a/tests/test_adapters.py +++ b/tests/test_adapters.py @@ -1,4 +1,10 @@ +from unittest import mock + +import pytest +from urllib3.exceptions import HTTPError as _HTTPError + import requests.adapters +from requests.exceptions import RequestException def test_request_url_trims_leading_path_separators(): @@ -6,3 +12,34 @@ def test_request_url_trims_leading_path_separators(): a = requests.adapters.HTTPAdapter() p = requests.Request(method="GET", url="http://127.0.0.1:10000//v:h").prepare() assert "/v:h" == a.request_url(p, {}) + + +def test_unknown_httperror_wrapped_in_requestexception(): + """Test that unknown urllib3 HTTPError types are wrapped in RequestException. + + When urllib3 raises an HTTPError that isn't explicitly + handled (not SSLError, ReadTimeoutError, or InvalidHeader), it should be + wrapped in RequestException rather than propagating as-is. + """ + adapter = requests.adapters.HTTPAdapter() + request = requests.Request(method="GET", url="http://example.com").prepare() + + # Create a generic HTTPError that doesn't match any specific handled types + generic_http_error = _HTTPError("Unknown HTTP error from urllib3") + + # Mock the connection to raise our generic HTTPError + with mock.patch.object( + adapter, 'get_connection_with_tls_context' + ) as mock_get_conn: + mock_conn = mock.MagicMock() + mock_conn.urlopen.side_effect = generic_http_error + mock_get_conn.return_value = mock_conn + + # The exception should be catchable as RequestException + with pytest.raises(RequestException) as exc_info: + adapter.send(request) + + # Verify it wraps the original error + assert exc_info.value.request == request + # Verify exception chaining + assert exc_info.value.__cause__ == generic_http_error