diff --git a/docs/2577.bugfix.rst b/docs/2577.bugfix.rst new file mode 100644 index 0000000000..ca77d76aca --- /dev/null +++ b/docs/2577.bugfix.rst @@ -0,0 +1 @@ +Changed HTTPSConnection so that ``proxy_ssl_context`` must be set when ``use_forwarding_for_https`` is set to ``True`` \ No newline at end of file diff --git a/src/urllib3/connection.py b/src/urllib3/connection.py index d3634e5654..50d115ee77 100644 --- a/src/urllib3/connection.py +++ b/src/urllib3/connection.py @@ -421,7 +421,22 @@ def __init__( self.key_file = key_file self.cert_file = cert_file self.key_password = key_password - self.ssl_context = ssl_context + + if proxy_config and proxy_config.use_forwarding_for_https and ssl_context: + if proxy_config.ssl_context: + raise ValueError( + "Parameter ssl_context cannot be set when use_forwarding_for_https is True" + ) + else: + raise ValueError( + "Parameter ssl_context cannot be set when use_forwarding_for_https is True. Set parameter proxy_ssl_context instead" + ) + + self.ssl_context = ( + proxy_config.ssl_context + if proxy_config and proxy_config.use_forwarding_for_https + else ssl_context + ) self.server_hostname = server_hostname self.ssl_version = None self.ssl_minimum_version = None diff --git a/test/with_dummyserver/test_proxy_poolmanager.py b/test/with_dummyserver/test_proxy_poolmanager.py index e3994f3f10..4edbdba7e8 100644 --- a/test/with_dummyserver/test_proxy_poolmanager.py +++ b/test/with_dummyserver/test_proxy_poolmanager.py @@ -394,6 +394,48 @@ def test_https_headers_forwarding_for_https(self) -> None: returned_headers.get("Host") == f"{self.https_host}:{self.https_port}" ) + def test_forwarding_for_https_with_proxy_ctx(self) -> None: + proxy_ctx = ssl.create_default_context() + proxy_ctx.load_verify_locations(DEFAULT_CA) + with proxy_from_url( + self.https_proxy_url, + headers={"Foo": "bar"}, + proxy_headers={"Hickory": "dickory"}, + proxy_ssl_context=proxy_ctx, + use_forwarding_for_https=True, + ) as http: + r = http.request("GET", f"{self.https_url}/") + assert r.status == 200 + + def test_forwarding_for_https_error_with_ssl_ctx(self) -> None: + proxy_ctx = ssl.create_default_context() + proxy_ctx.load_verify_locations(DEFAULT_CA) + ctx = ssl.create_default_context() + ctx.load_verify_locations(DEFAULT_CA) + with proxy_from_url( + self.https_proxy_url, + proxy_ssl_context=proxy_ctx, + use_forwarding_for_https=True, + ssl_context=ctx, + ) as proxy: + with pytest.raises( + ValueError, + match="Parameter ssl_context cannot be set when use_forwarding_for_https is True", + ): + proxy.request("GET", self.https_url) + + def test_forwarding_for_https_error_with_only_ssl_ctx(self) -> None: + ctx = ssl.create_default_context() + ctx.load_verify_locations(DEFAULT_CA) + with proxy_from_url( + self.https_proxy_url, use_forwarding_for_https=True, ssl_context=ctx + ) as proxy: + with pytest.raises( + ValueError, + match="Parameter ssl_context cannot be set when use_forwarding_for_https is True. Set parameter proxy_ssl_context instead", + ): + proxy.request("GET", self.https_url) + def test_headerdict(self) -> None: default_headers = HTTPHeaderDict(a="b") proxy_headers = HTTPHeaderDict() @@ -571,19 +613,13 @@ def test_https_proxy_tls_error( @requires_network() @pytest.mark.parametrize( - ["proxy_scheme", "use_forwarding_for_https"], + ["proxy_scheme"], [ - ("http", False), - ("https", False), - ("https", True), + ("http",), + ("https",), ], ) - def test_proxy_https_target_tls_error( - self, proxy_scheme: str, use_forwarding_for_https: str - ) -> None: - if proxy_scheme == "https" and use_forwarding_for_https: - pytest.skip("Test is expected to fail due to urllib3/urllib3#2577") - + def test_proxy_https_target_tls_error(self, proxy_scheme: str) -> None: proxy_url = self.https_proxy_url if proxy_scheme == "https" else self.proxy_url proxy_ctx = ssl.create_default_context() proxy_ctx.load_verify_locations(DEFAULT_CA) @@ -593,7 +629,7 @@ def test_proxy_https_target_tls_error( proxy_url, proxy_ssl_context=proxy_ctx, ssl_context=ctx, - use_forwarding_for_https=use_forwarding_for_https, + use_forwarding_for_https=False, ) as proxy: with pytest.raises(MaxRetryError) as e: proxy.request("GET", self.https_url)