Skip to content

aiohttp 3.12.0 catches OsError exceptions, hiding the ProxyTimeoutError and ProxyConnectionError errors #52

@vEpiphyte

Description

@vEpiphyte

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)]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions