Skip to content

Commit c6a61ab

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 c6a61ab

4 files changed

Lines changed: 49 additions & 46 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: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import asyncio
66
import logging
77
import threading
8+
9+
import anyio
810
import httpcore
911
import httpx
1012
from httpx_socks import AsyncProxyTransport
@@ -30,15 +32,18 @@
3032
LOOP = None
3133
SSLCONTEXTS = {}
3234
TRANSPORT_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
3944
async 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
6368
class 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

7077
class 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

110115
class 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

139144
def 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(

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)