55import asyncio
66import logging
77import threading
8+
9+ import anyio
810import httpcore
911import httpx
1012from httpx_socks import AsyncProxyTransport
3032LOOP = None
3133SSLCONTEXTS = {}
3234TRANSPORT_KWARGS = {
33- 'backend' : 'asyncio' ,
35+ # use anyio :
36+ # * https://github.com/encode/httpcore/issues/344
37+ # * https://github.com/encode/httpx/discussions/1511
38+ 'backend' : 'anyio' ,
3439 'trust_env' : False ,
3540}
3641
3742
3843# pylint: disable=protected-access
3944async def close_connections_for_url (
40- connection_pool : httpcore .AsyncConnectionPool ,
41- url : httpcore . _utils . URL ):
45+ connection_pool : httpcore .AsyncConnectionPool , url : httpcore . _utils . URL
46+ ):
4247
4348 origin = httpcore ._utils .url_to_origin (url )
4449 logger .debug ('Drop connections for %r' , origin )
@@ -63,77 +68,77 @@ def get_sslcontexts(proxy_url=None, cert=None, verify=True, trust_env=True, http
6368class AsyncHTTPTransportNoHttp (httpcore .AsyncHTTPTransport ):
6469 """Block HTTP request"""
6570
66- async def arequest (self , method , url , headers = None , stream = None , ext = None ):
67- raise httpcore .UnsupportedProtocol ("HTTP protocol is disabled" )
71+ async def handle_async_request (
72+ self , method , url , headers = None , stream = None , extensions = None
73+ ):
74+ raise httpcore .UnsupportedProtocol ('HTTP protocol is disabled' )
6875
6976
7077class AsyncProxyTransportFixed (AsyncProxyTransport ):
7178 """Fix httpx_socks.AsyncProxyTransport
7279
73- Map python_socks exceptions to httpcore.ProxyError
80+ Map python_socks exceptions to httpcore.ProxyError / httpcore.ConnectError
7481
7582 Map socket.gaierror to httpcore.ConnectError
7683
77- Note: keepalive_expiry is ignored, AsyncProxyTransport should call:
78- * self._keepalive_sweep()
79- * self._response_closed(self, connection)
80-
8184 Note: AsyncProxyTransport inherit from AsyncConnectionPool
82-
83- Note: the API is going to change on httpx 0.18.0
84- see https://github.com/encode/httpx/pull/1522
8585 """
8686
87- async def arequest (self , method , url , headers = None , stream = None , ext = None ):
87+ async def handle_async_request (
88+ self , method , url , headers = None , stream = None , extensions = None
89+ ):
8890 retry = 2
8991 while retry > 0 :
9092 retry -= 1
9193 try :
92- return await super ().arequest (method , url , headers , stream , ext )
94+ return await super ().handle_async_request (
95+ method , url , headers = headers , stream = stream , extensions = extensions
96+ )
9397 except (ProxyConnectionError , ProxyTimeoutError , ProxyError ) as e :
94- raise httpcore .ProxyError ( e )
98+ raise httpcore .ProxyError from e
9599 except OSError as e :
96100 # socket.gaierror when DNS resolution fails
97- raise httpcore .NetworkError (e )
98- except httpcore .RemoteProtocolError as e :
101+ raise httpcore .ConnectError from e
102+ except httpcore .NetworkError as e :
103+ # https://github.com/encode/httpcore/pull/313
104+ await close_connections_for_url (self , url )
105+ raise e
106+ except (httpcore .RemoteProtocolError , anyio .BrokenResourceError ) as e :
99107 # in case of httpcore.RemoteProtocolError: Server disconnected
108+ # https://github.com/encode/httpcore/pull/129
109+ # or https://github.com/encode/httpcore/issues/382
100110 await close_connections_for_url (self , url )
101111 logger .warning ('httpcore.RemoteProtocolError: retry' , exc_info = e )
102112 # retry
103- except (httpcore .NetworkError , httpcore .ProtocolError ) as e :
104- # httpcore.WriteError on HTTP/2 connection leaves a new opened stream
105- # then each new request creates a new stream and raise the same WriteError
106- await close_connections_for_url (self , url )
107- raise e
108113
109114
110115class AsyncHTTPTransportFixed (httpx .AsyncHTTPTransport ):
111116 """Fix httpx.AsyncHTTPTransport"""
112117
113- async def arequest (self , method , url , headers = None , stream = None , ext = None ):
118+ async def handle_async_request (
119+ self , method , url , headers = None , stream = None , extensions = None
120+ ):
114121 retry = 2
115122 while retry > 0 :
116123 retry -= 1
117124 try :
118- return await super ().arequest (method , url , headers , stream , ext )
125+ return await super ().handle_async_request (
126+ method , url , headers = headers , stream = stream , extensions = extensions
127+ )
119128 except OSError as e :
120129 # socket.gaierror when DNS resolution fails
121- raise httpcore .ConnectError (e )
122- except httpcore .CloseError as e :
123- # httpcore.CloseError: [Errno 104] Connection reset by peer
124- # raised by _keepalive_sweep()
125- # from https://github.com/encode/httpcore/blob/4b662b5c42378a61e54d673b4c949420102379f5/httpcore/_backends/asyncio.py#L198 # pylint: disable=line-too-long
126- await close_connections_for_url (self ._pool , url )
127- logger .warning ('httpcore.CloseError: retry' , exc_info = e )
128- # retry
129- except httpcore .RemoteProtocolError as e :
130+ raise httpcore .ConnectError from e
131+ except httpcore .NetworkError as e :
132+ # https://github.com/encode/httpcore/pull/313
133+ await close_connections_for_url (self , url )
134+ raise e
135+ except (httpcore .RemoteProtocolError , anyio .BrokenResourceError ) as e :
130136 # in case of httpcore.RemoteProtocolError: Server disconnected
137+ # https://github.com/encode/httpcore/pull/129
138+ # or https://github.com/encode/httpcore/issues/382
131139 await close_connections_for_url (self ._pool , url )
132140 logger .warning ('httpcore.RemoteProtocolError: retry' , exc_info = e )
133141 # retry
134- except (httpcore .ProtocolError , httpcore .NetworkError ) as e :
135- await close_connections_for_url (self ._pool , url )
136- raise e
137142
138143
139144def get_transport_for_socks_proxy (verify , http2 , local_address , proxy_url , limit , retries ):
@@ -206,7 +211,7 @@ def new_client(
206211 if not enable_http and (pattern == 'http' or pattern .startswith ('http://' )):
207212 continue
208213 if (proxy_url .startswith ('socks4://' )
209- or proxy_url .startswith ('socks5://' )
214+ or proxy_url .startswith ('socks5://' )
210215 or proxy_url .startswith ('socks5h://' )
211216 ):
212217 mounts [pattern ] = get_transport_for_socks_proxy (
0 commit comments