| @@ -114,7 +114,7 @@ aiohttp usage | |||||
| import asyncio | import asyncio | ||||
| import aiohttp | import aiohttp | ||||
| import aiosocks | import aiosocks | ||||
| from aiosocks.connector import SocksConnector | |||||
| from aiosocks.connector import SocksConnector, proxy_connector | |||||
| async def load_github_main(): | async def load_github_main(): | ||||
| @@ -122,11 +122,21 @@ aiohttp usage | |||||
| auth = aiosocks.Socks5Auth('proxyuser1', password='pwd') | auth = aiosocks.Socks5Auth('proxyuser1', password='pwd') | ||||
| # remote resolve | # remote resolve | ||||
| # conn = SocksConnector(proxy=addr, proxy_auth=auth, remote_resolve=True) | |||||
| conn = SocksConnector(proxy=addr, proxy_auth=auth, remote_resolve=True) | |||||
| # or locale resolve | # or locale resolve | ||||
| conn = SocksConnector(proxy=addr, proxy_auth=auth, remote_resolve=False) | conn = SocksConnector(proxy=addr, proxy_auth=auth, remote_resolve=False) | ||||
| # or use shortcut function for automatically create | |||||
| # SocksConnector/aiohttp.ProxyConnector (socks or http proxy) | |||||
| conn = proxy_connector(aiosocks.SocksAddr(...), | |||||
| remote_resolve=True, verify_ssl=False) | |||||
| # return SocksConnector | |||||
| conn = proxy_connector(aiosocks.HttpProxyAddr('http://proxy'), | |||||
| aiosocks.HttpProxyAuth('login', 'pwd')) | |||||
| # return aiohttp.ProxyConnector (http proxy connector) | |||||
| try: | try: | ||||
| with aiohttp.ClientSession(connector=conn) as ses: | with aiohttp.ClientSession(connector=conn) as ses: | ||||
| async with session.get('http://github.com/') as resp: | async with session.get('http://github.com/') as resp: | ||||
| @@ -4,17 +4,19 @@ from .errors import ( | |||||
| SocksConnectionError, InvalidServerReply, InvalidServerVersion | SocksConnectionError, InvalidServerReply, InvalidServerVersion | ||||
| ) | ) | ||||
| from .helpers import ( | from .helpers import ( | ||||
| SocksAddr, Socks4Addr, Socks5Addr, Socks4Auth, Socks5Auth | |||||
| SocksAddr, Socks4Addr, Socks5Addr, Socks4Auth, | |||||
| Socks5Auth, HttpProxyAddr, HttpProxyAuth | |||||
| ) | ) | ||||
| from .protocols import Socks4Protocol, Socks5Protocol, DEFAULT_LIMIT | from .protocols import Socks4Protocol, Socks5Protocol, DEFAULT_LIMIT | ||||
| __version__ = '0.1.4' | __version__ = '0.1.4' | ||||
| __all__ = ('Socks4Protocol', 'Socks5Protocol', 'Socks4Auth', | __all__ = ('Socks4Protocol', 'Socks5Protocol', 'Socks4Auth', | ||||
| 'Socks5Auth', 'Socks4Addr', 'Socks5Addr', 'SocksError', | |||||
| 'NoAcceptableAuthMethods', 'LoginAuthenticationFailed', | |||||
| 'SocksConnectionError', 'InvalidServerVersion', | |||||
| 'InvalidServerReply', 'create_connection', 'open_connection') | |||||
| 'Socks5Auth', 'Socks4Addr', 'Socks5Addr', 'HttpProxyAddr', | |||||
| 'HttpProxyAuth', 'SocksError', 'NoAcceptableAuthMethods', | |||||
| 'LoginAuthenticationFailed', 'SocksConnectionError', | |||||
| 'InvalidServerVersion', 'InvalidServerReply', | |||||
| 'create_connection', 'open_connection') | |||||
| @asyncio.coroutine | @asyncio.coroutine | ||||
| @@ -4,6 +4,7 @@ import aiohttp | |||||
| import ipaddress | import ipaddress | ||||
| from aiohttp.errors import ProxyConnectionError | from aiohttp.errors import ProxyConnectionError | ||||
| from .errors import SocksError, SocksConnectionError | from .errors import SocksError, SocksConnectionError | ||||
| from .helpers import HttpProxyAddr, SocksAddr | |||||
| from . import create_connection | from . import create_connection | ||||
| __all__ = ('SocksConnector',) | __all__ = ('SocksConnector',) | ||||
| @@ -108,3 +109,13 @@ class SocksConnector(aiohttp.TCPConnector): | |||||
| raise aiohttp.ClientOSError( | raise aiohttp.ClientOSError( | ||||
| exc.errno, 'Can not connect to %s:%s [%s]' % | exc.errno, 'Can not connect to %s:%s [%s]' % | ||||
| (req.host, req.port, exc.strerror)) from exc | (req.host, req.port, exc.strerror)) from exc | ||||
| def proxy_connector(proxy, proxy_auth=None, **kwargs): | |||||
| if isinstance(proxy, HttpProxyAddr): | |||||
| return aiohttp.ProxyConnector( | |||||
| proxy.url, proxy_auth=proxy_auth, **kwargs) | |||||
| elif isinstance(proxy, SocksAddr): | |||||
| return SocksConnector(proxy, proxy_auth, **kwargs) | |||||
| else: | |||||
| raise ValueError('Unsupported `proxy` format') | |||||
| @@ -1,6 +1,8 @@ | |||||
| from collections import namedtuple | from collections import namedtuple | ||||
| from aiohttp.helpers import BasicAuth as HttpProxyAuth | |||||
| __all__ = ('Socks4Auth', 'Socks5Auth', 'Socks4Addr', 'Socks5Addr', 'SocksAddr') | |||||
| __all__ = ('Socks4Auth', 'Socks5Auth', 'Socks4Addr', 'Socks5Addr', 'SocksAddr', | |||||
| 'HttpProxyAddr', 'HttpProxyAuth') | |||||
| class Socks4Auth(namedtuple('Socks4Auth', ['login', 'encoding'])): | class Socks4Auth(namedtuple('Socks4Auth', ['login', 'encoding'])): | ||||
| @@ -41,3 +43,10 @@ class Socks4Addr(SocksAddr): | |||||
| class Socks5Addr(SocksAddr): | class Socks5Addr(SocksAddr): | ||||
| pass | pass | ||||
| class HttpProxyAddr(namedtuple('HttpProxyAddr', ['url'])): | |||||
| def __new__(cls, url): | |||||
| if url is None: | |||||
| raise ValueError('None is not allowed as url value') | |||||
| return super().__new__(cls, url) | |||||
| @@ -2,9 +2,10 @@ import unittest | |||||
| import asyncio | import asyncio | ||||
| import aiosocks | import aiosocks | ||||
| import aiohttp | import aiohttp | ||||
| import pytest | |||||
| from unittest import mock | from unittest import mock | ||||
| from aiohttp.client_reqrep import ClientRequest | from aiohttp.client_reqrep import ClientRequest | ||||
| from aiosocks.connector import SocksConnector | |||||
| from aiosocks.connector import SocksConnector, proxy_connector | |||||
| from .helpers import fake_coroutine | from .helpers import fake_coroutine | ||||
| @@ -131,3 +132,19 @@ class TestSocksConnector(unittest.TestCase): | |||||
| with self.assertRaises(aiosocks.SocksError): | with self.assertRaises(aiosocks.SocksError): | ||||
| self.loop.run_until_complete(connector.connect(req)) | self.loop.run_until_complete(connector.connect(req)) | ||||
| def test_proxy_connector(): | |||||
| socks4_addr = aiosocks.Socks4Addr('h') | |||||
| socks5_addr = aiosocks.Socks5Addr('h') | |||||
| http_addr = aiosocks.HttpProxyAddr('http://proxy') | |||||
| loop = asyncio.new_event_loop() | |||||
| assert isinstance(proxy_connector(socks4_addr, loop=loop), SocksConnector) | |||||
| assert isinstance(proxy_connector(socks5_addr, loop=loop), SocksConnector) | |||||
| assert isinstance(proxy_connector(http_addr, loop=loop), | |||||
| aiohttp.ProxyConnector) | |||||
| with pytest.raises(ValueError): | |||||
| proxy_connector(None) | |||||
| @@ -83,3 +83,11 @@ def test_socks5_addr4(): | |||||
| addr = aiosocks.Socks5Addr('localhost', None) | addr = aiosocks.Socks5Addr('localhost', None) | ||||
| assert addr.host == 'localhost' | assert addr.host == 'localhost' | ||||
| assert addr.port == 1080 | assert addr.port == 1080 | ||||
| def test_http_proxy_addr(): | |||||
| addr = aiosocks.HttpProxyAddr('http://proxy') | |||||
| assert addr.url == 'http://proxy' | |||||
| with pytest.raises(ValueError): | |||||
| aiosocks.HttpProxyAddr(None) | |||||