With the latest aiohttp 3.12.0 release, the ProxyTimeoutError and ProxyConnectionError error classes ( from python-socks ) can be caught as OsError here; which will raise them as an aiohttp.client_exceptions.ClientOSError. This can be confusing for users who are trying to handle Proxy specific errors. The following example scripts show the change in behavior:
Script:
import sys
import asyncio
import argparse
import aiohttp
import aiohttp_socks
async def main(argv):
pars = argparse.ArgumentParser()
pars.add_argument('url', default='https://www.google.com')
pars.add_argument('--proxy', type=str, default=None)
opts = pars.parse_args(argv)
connector = None
if opts.proxy:
connector = aiohttp_socks.ProxyConnector.from_url(opts.proxy)
timeout = aiohttp.ClientTimeout(total=300)
async with aiohttp.ClientSession(connector=connector, timeout=timeout) as sess:
async with sess.get(opts.url) as resp:
print(resp)
if __name__ == '__main__':
sys.exit(asyncio.run(main(sys.argv[1:])))
Failing with aiohttp 3.12.0 ( this was run in a docker container via docker run --rm -it --entrypoint /bin/bash -v pwd/aiohttp_socks_proxy_err.py:/tmp/aiohttp_socks_proxy_err.py python:3.11.12 )
root@8b1a6c2025c1:/#
aiohttp==3.12.0
aiohttp_socks==0.10.1
python-socks==2.7.1
root@8b1a6c2025c1:/# python /tmp/aiohttp_socks_proxy_err.py 'https://google.com' --proxy 'socks5://user:pass@127.0.0.1:1'
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/python_socks/async_/asyncio/v2/_proxy.py", line 97, in _connect
stream = await connect_tcp(
^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/python_socks/async_/asyncio/v2/_connect.py", line 16, in connect_tcp
reader, writer = await asyncio.open_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/streams.py", line 48, in open_connection
transport, _ = await loop.create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/base_events.py", line 1086, in create_connection
raise exceptions[0]
File "/usr/local/lib/python3.11/asyncio/base_events.py", line 1070, in create_connection
sock = await self._connect_sock(
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/base_events.py", line 974, in _connect_sock
await self.sock_connect(sock, address)
File "/usr/local/lib/python3.11/asyncio/selector_events.py", line 638, in sock_connect
return await fut
^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/selector_events.py", line 678, in _sock_connect_cb
raise OSError(err, f'Connect call failed {address}')
ConnectionRefusedError: [Errno 111] Connect call failed ('127.0.0.1', 1)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/aiohttp/client.py", line 760, in _request
resp = await handler(req)
^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/client.py", line 715, in _connect_and_send_request
conn = await self._connector.connect(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/connector.py", line 561, in connect
proto = await self._create_connection(req, traces, timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/connector.py", line 1074, in _create_connection
_, proto = await self._create_direct_connection(req, traces, timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/connector.py", line 1394, in _create_direct_connection
transp, proto = await self._wrap_create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp_socks/connector.py", line 66, in _wrap_create_connection
return await self._connect_via_proxy(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp_socks/connector.py", line 123, in _connect_via_proxy
stream = await proxy.connect(
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/python_socks/async_/asyncio/v2/_proxy.py", line 79, in connect
return await self._connect(
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/python_socks/async_/asyncio/v2/_proxy.py", line 104, in _connect
raise ProxyConnectionError(
python_socks._errors.ProxyConnectionError: [Errno 111] Couldn't connect to proxy 127.0.0.1:1 [Connect call failed ('127.0.0.1', 1)]
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/tmp/aiohttp_socks_proxy_err.py", line 22, in <module>
sys.exit(asyncio.run(main(sys.argv[1:])))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/base_events.py", line 654, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "/tmp/aiohttp_socks_proxy_err.py", line 18, in main
async with sess.get(opts.url) as resp:
File "/usr/local/lib/python3.11/site-packages/aiohttp/client.py", line 1457, in __aenter__
self._resp: _RetType = await self._coro
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/client.py", line 779, in _request
raise ClientOSError(*exc.args) from exc
aiohttp.client_exceptions.ClientOSError: [Errno 111] Couldn't connect to proxy 127.0.0.1:1 [Connect call failed ('127.0.0.1', 1)]
This is the old behavior with aiohttp 3.11.8:
root@e0aeb1dc70ee:/# python -m pip freeze | grep -E "aiohttp|socks"
aiohttp==3.11.18
aiohttp_socks==0.10.1
python-socks==2.7.1
root@e0aeb1dc70ee:/# python /tmp/aiohttp_socks_proxy_err.py 'https://google.com' --proxy 'socks5://user:pass@127.0.0.1:1'
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/python_socks/async_/asyncio/v2/_proxy.py", line 97, in _connect
stream = await connect_tcp(
^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/python_socks/async_/asyncio/v2/_connect.py", line 16, in connect_tcp
reader, writer = await asyncio.open_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/streams.py", line 48, in open_connection
transport, _ = await loop.create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/base_events.py", line 1086, in create_connection
raise exceptions[0]
File "/usr/local/lib/python3.11/asyncio/base_events.py", line 1070, in create_connection
sock = await self._connect_sock(
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/base_events.py", line 974, in _connect_sock
await self.sock_connect(sock, address)
File "/usr/local/lib/python3.11/asyncio/selector_events.py", line 638, in sock_connect
return await fut
^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/selector_events.py", line 678, in _sock_connect_cb
raise OSError(err, f'Connect call failed {address}')
ConnectionRefusedError: [Errno 111] Connect call failed ('127.0.0.1', 1)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/tmp/aiohttp_socks_proxy_err.py", line 22, in <module>
sys.exit(asyncio.run(main(sys.argv[1:])))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/base_events.py", line 654, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "/tmp/aiohttp_socks_proxy_err.py", line 18, in main
async with sess.get(opts.url) as resp:
File "/usr/local/lib/python3.11/site-packages/aiohttp/client.py", line 1425, in __aenter__
self._resp: _RetType = await self._coro
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/client.py", line 703, in _request
conn = await self._connector.connect(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/connector.py", line 548, in connect
proto = await self._create_connection(req, traces, timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/connector.py", line 1056, in _create_connection
_, proto = await self._create_direct_connection(req, traces, timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/connector.py", line 1375, in _create_direct_connection
transp, proto = await self._wrap_create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp_socks/connector.py", line 66, in _wrap_create_connection
return await self._connect_via_proxy(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp_socks/connector.py", line 123, in _connect_via_proxy
stream = await proxy.connect(
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/python_socks/async_/asyncio/v2/_proxy.py", line 79, in connect
return await self._connect(
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/python_socks/async_/asyncio/v2/_proxy.py", line 104, in _connect
raise ProxyConnectionError(
python_socks._errors.ProxyConnectionError: [Errno 111] Couldn't connect to proxy 127.0.0.1:1 [Connect call failed ('127.0.0.1', 1)]
With the latest
aiohttp3.12.0 release, theProxyTimeoutErrorandProxyConnectionErrorerror classes ( frompython-socks) can be caught asOsErrorhere; which will raise them as anaiohttp.client_exceptions.ClientOSError. This can be confusing for users who are trying to handle Proxy specific errors. The following example scripts show the change in behavior:Script:
Failing with aiohttp 3.12.0 ( this was run in a docker container via docker run --rm -it --entrypoint /bin/bash -v
pwd/aiohttp_socks_proxy_err.py:/tmp/aiohttp_socks_proxy_err.py python:3.11.12 )This is the old behavior with aiohttp 3.11.8: