Skip to content

Commit 9a16bae

Browse files
committed
[upd] upgrade httpx 0.19.0
adjust searx.network module to the new internal API see encode/httpx#1522
1 parent 602cbc2 commit 9a16bae

4 files changed

Lines changed: 53 additions & 53 deletions

File tree

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ lxml==4.6.3
77
pygments==2.10.0
88
python-dateutil==2.8.2
99
pyyaml==5.4.1
10-
httpx[http2]==0.17.1
10+
httpx[http2]==0.19.0
1111
Brotli==1.0.9
1212
uvloop==0.16.0; python_version >= '3.7'
1313
uvloop==0.14.0; python_version < '3.7'
14-
httpx-socks[asyncio]==0.3.1
14+
httpx-socks[asyncio]==0.4.1
1515
langdetect==1.0.9
1616
setproctitle==1.2.2

searx/network/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ async def stream_chunk_to_queue(network, queue, method, url, **kwargs):
172172
async for chunk in response.aiter_raw(65536):
173173
if len(chunk) > 0:
174174
queue.put(chunk)
175-
except httpx.ResponseClosed:
175+
except httpx.StreamClosed:
176176
# the response was queued before the exception.
177177
# the exception was raised on aiter_raw.
178178
# we do nothing here: in the finally block, None will be queued

searx/network/client.py

Lines changed: 47 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import asyncio
66
import logging
77
import threading
8+
89
import httpcore
910
import httpx
1011
from httpx_socks import AsyncProxyTransport
@@ -26,19 +27,22 @@
2627
uvloop.install()
2728

2829

29-
logger = logger.getChild('searx.http.client')
30+
logger = logger.getChild('searx.network.client')
3031
LOOP = None
3132
SSLCONTEXTS = {}
3233
TRANSPORT_KWARGS = {
33-
'backend': 'asyncio',
34+
# use anyio :
35+
# * https://github.com/encode/httpcore/issues/344
36+
# * https://github.com/encode/httpx/discussions/1511
37+
'backend': 'anyio',
3438
'trust_env': False,
3539
}
3640

3741

3842
# pylint: disable=protected-access
3943
async def close_connections_for_url(
40-
connection_pool: httpcore.AsyncConnectionPool,
41-
url: httpcore._utils.URL ):
44+
connection_pool: httpcore.AsyncConnectionPool, url: httpcore._utils.URL
45+
):
4246

4347
origin = httpcore._utils.url_to_origin(url)
4448
logger.debug('Drop connections for %r', origin)
@@ -47,7 +51,7 @@ async def close_connections_for_url(
4751
await connection_pool._remove_from_pool(connection)
4852
try:
4953
await connection.aclose()
50-
except httpcore.NetworkError as e:
54+
except httpx.NetworkError as e:
5155
logger.warning('Error closing an existing connection', exc_info=e)
5256
# pylint: enable=protected-access
5357

@@ -60,80 +64,78 @@ def get_sslcontexts(proxy_url=None, cert=None, verify=True, trust_env=True, http
6064
return SSLCONTEXTS[key]
6165

6266

63-
class AsyncHTTPTransportNoHttp(httpcore.AsyncHTTPTransport):
67+
class AsyncHTTPTransportNoHttp(httpx.AsyncHTTPTransport):
6468
"""Block HTTP request"""
6569

66-
async def arequest(self, method, url, headers=None, stream=None, ext=None):
67-
raise httpcore.UnsupportedProtocol("HTTP protocol is disabled")
70+
async def handle_async_request(
71+
self, method, url, headers=None, stream=None, extensions=None
72+
):
73+
raise httpx.UnsupportedProtocol('HTTP protocol is disabled')
6874

6975

7076
class AsyncProxyTransportFixed(AsyncProxyTransport):
7177
"""Fix httpx_socks.AsyncProxyTransport
7278
73-
Map python_socks exceptions to httpcore.ProxyError
74-
75-
Map socket.gaierror to httpcore.ConnectError
79+
Map python_socks exceptions to httpx.ProxyError / httpx.ConnectError
7680
77-
Note: keepalive_expiry is ignored, AsyncProxyTransport should call:
78-
* self._keepalive_sweep()
79-
* self._response_closed(self, connection)
81+
Map socket.gaierror to httpx.ConnectError
8082
8183
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
8584
"""
8685

87-
async def arequest(self, method, url, headers=None, stream=None, ext=None):
86+
async def handle_async_request(
87+
self, method, url, headers=None, stream=None, extensions=None
88+
):
8889
retry = 2
8990
while retry > 0:
9091
retry -= 1
9192
try:
92-
return await super().arequest(method, url, headers, stream, ext)
93+
return await super().handle_async_request(
94+
method, url, headers=headers, stream=stream, extensions=extensions
95+
)
9396
except (ProxyConnectionError, ProxyTimeoutError, ProxyError) as e:
94-
raise httpcore.ProxyError(e)
97+
raise httpx.ProxyError from e
9598
except OSError as e:
9699
# socket.gaierror when DNS resolution fails
97-
raise httpcore.NetworkError(e)
98-
except httpcore.RemoteProtocolError as e:
99-
# in case of httpcore.RemoteProtocolError: Server disconnected
100-
await close_connections_for_url(self, url)
101-
logger.warning('httpcore.RemoteProtocolError: retry', exc_info=e)
102-
# retry
103-
except (httpcore.NetworkError, httpcore.ProtocolError) as e:
104-
# httpcore.WriteError on HTTP/2 connection leaves a new opened stream
100+
raise httpx.ConnectError from e
101+
except httpx.NetworkError as e:
102+
# httpx.WriteError on HTTP/2 connection leaves a new opened stream
105103
# then each new request creates a new stream and raise the same WriteError
106104
await close_connections_for_url(self, url)
107105
raise e
106+
except httpx.RemoteProtocolError as e:
107+
# in case of httpx.RemoteProtocolError: Server disconnected
108+
await close_connections_for_url(self, url)
109+
logger.warning('httpx.RemoteProtocolError: retry', exc_info=e)
110+
# retry
108111

109112

110113
class AsyncHTTPTransportFixed(httpx.AsyncHTTPTransport):
111114
"""Fix httpx.AsyncHTTPTransport"""
112115

113-
async def arequest(self, method, url, headers=None, stream=None, ext=None):
116+
async def handle_async_request(
117+
self, method, url, headers=None, stream=None, extensions=None
118+
):
114119
retry = 2
115120
while retry > 0:
116121
retry -= 1
117122
try:
118-
return await super().arequest(method, url, headers, stream, ext)
123+
return await super().handle_async_request(
124+
method, url, headers=headers, stream=stream, extensions=extensions
125+
)
119126
except OSError as e:
120127
# 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-
# in case of httpcore.RemoteProtocolError: Server disconnected
128+
raise httpx.ConnectError from e
129+
except httpx.NetworkError as e:
130+
# httpx.WriteError on HTTP/2 connection leaves a new opened stream
131+
# then each new request creates a new stream and raise the same WriteError
132+
await close_connections_for_url(self, url)
133+
raise e
134+
except httpx.RemoteProtocolError as e:
135+
# in case of httpx.RemoteProtocolError: Server disconnected
131136
await close_connections_for_url(self._pool, url)
132-
logger.warning('httpcore.RemoteProtocolError: retry', exc_info=e)
137+
logger.warning('httpx.RemoteProtocolError: retry', exc_info=e)
133138
# retry
134-
except (httpcore.ProtocolError, httpcore.NetworkError) as e:
135-
await close_connections_for_url(self._pool, url)
136-
raise e
137139

138140

139141
def get_transport_for_socks_proxy(verify, http2, local_address, proxy_url, limit, retries):
@@ -206,7 +208,7 @@ def new_client(
206208
if not enable_http and (pattern == 'http' or pattern.startswith('http://')):
207209
continue
208210
if (proxy_url.startswith('socks4://')
209-
or proxy_url.startswith('socks5://')
211+
or proxy_url.startswith('socks5://')
210212
or proxy_url.startswith('socks5h://')
211213
):
212214
mounts[pattern] = get_transport_for_socks_proxy(

searx/network/network.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,10 @@ async def log_response(self, response: httpx.Response):
138138
request = response.request
139139
status = f"{response.status_code} {response.reason_phrase}"
140140
response_line = f"{response.http_version} {status}"
141-
if hasattr(response, "_elapsed"):
142-
elapsed_time = f"{response.elapsed.total_seconds()} sec"
143-
else:
144-
elapsed_time = "stream"
141+
content_type = response.headers.get("Content-Type")
142+
content_type = f' ({content_type})' if content_type else ''
145143
self._logger.debug(
146-
f'HTTP Request: {request.method} {request.url} "{response_line}" ({elapsed_time})'
144+
f'HTTP Request: {request.method} {request.url} "{response_line}"{content_type}'
147145
)
148146

149147
def get_client(self, verify=None, max_redirects=None):

0 commit comments

Comments
 (0)