@@ -224,7 +224,7 @@ async def test_proxy_tunneling_with_403():
224224 """
225225 network_backend = AsyncMockBackend (
226226 [
227- b"HTTP/1.1 403 Permission Denied\r \n " b" \r \n " ,
227+ b"HTTP/1.1 403 Permission Denied\r \n \r \n " ,
228228 ]
229229 )
230230
@@ -276,3 +276,45 @@ def test_proxy_headers():
276276 assert proxy .headers == [
277277 (b"Proxy-Authorization" , b"Basic dXNlcm5hbWU6cGFzc3dvcmQ=" )
278278 ]
279+
280+
281+ @pytest .mark .anyio
282+ async def test_proxy_tunneling_tls_error ():
283+ """
284+ Send an HTTPS request via a proxy, but the TLS handshake fails.
285+ """
286+
287+ class BrokenTLSStream (AsyncMockStream ):
288+ async def start_tls (
289+ self ,
290+ ssl_context : ssl .SSLContext ,
291+ server_hostname : typing .Optional [str ] = None ,
292+ timeout : typing .Optional [float ] = None ,
293+ ) -> AsyncNetworkStream :
294+ raise OSError ("TLS Failure" )
295+
296+ class BrokenTLSBackend (AsyncMockBackend ):
297+ async def connect_tcp (
298+ self ,
299+ host : str ,
300+ port : int ,
301+ timeout : typing .Optional [float ] = None ,
302+ local_address : typing .Optional [str ] = None ,
303+ socket_options : typing .Optional [typing .Iterable [SOCKET_OPTION ]] = None ,
304+ ) -> AsyncNetworkStream :
305+ return BrokenTLSStream (list (self ._buffer ))
306+
307+ network_backend = BrokenTLSBackend (
308+ [
309+ b"HTTP/1.1 200 OK\r \n \r \n " ,
310+ ]
311+ )
312+
313+ async with AsyncConnectionPool (
314+ proxy = Proxy ("http://localhost:8080/" ),
315+ network_backend = network_backend ,
316+ ) as proxy :
317+ with pytest .raises (OSError , match = "TLS Failure" ):
318+ await proxy .request ("GET" , "https://example.com/" )
319+
320+ assert not proxy .connections
0 commit comments