Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/urllib3/contrib/socks.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:32:28 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:d30785e31577 | 1:56ad4e20f292 |
|---|---|
| 1 # -*- coding: utf-8 -*- | |
| 2 """ | |
| 3 This module contains provisional support for SOCKS proxies from within | |
| 4 urllib3. This module supports SOCKS4, SOCKS4A (an extension of SOCKS4), and | |
| 5 SOCKS5. To enable its functionality, either install PySocks or install this | |
| 6 module with the ``socks`` extra. | |
| 7 | |
| 8 The SOCKS implementation supports the full range of urllib3 features. It also | |
| 9 supports the following SOCKS features: | |
| 10 | |
| 11 - SOCKS4A (``proxy_url='socks4a://...``) | |
| 12 - SOCKS4 (``proxy_url='socks4://...``) | |
| 13 - SOCKS5 with remote DNS (``proxy_url='socks5h://...``) | |
| 14 - SOCKS5 with local DNS (``proxy_url='socks5://...``) | |
| 15 - Usernames and passwords for the SOCKS proxy | |
| 16 | |
| 17 .. note:: | |
| 18 It is recommended to use ``socks5h://`` or ``socks4a://`` schemes in | |
| 19 your ``proxy_url`` to ensure that DNS resolution is done from the remote | |
| 20 server instead of client-side when connecting to a domain name. | |
| 21 | |
| 22 SOCKS4 supports IPv4 and domain names with the SOCKS4A extension. SOCKS5 | |
| 23 supports IPv4, IPv6, and domain names. | |
| 24 | |
| 25 When connecting to a SOCKS4 proxy the ``username`` portion of the ``proxy_url`` | |
| 26 will be sent as the ``userid`` section of the SOCKS request:: | |
| 27 | |
| 28 proxy_url="socks4a://<userid>@proxy-host" | |
| 29 | |
| 30 When connecting to a SOCKS5 proxy the ``username`` and ``password`` portion | |
| 31 of the ``proxy_url`` will be sent as the username/password to authenticate | |
| 32 with the proxy:: | |
| 33 | |
| 34 proxy_url="socks5h://<username>:<password>@proxy-host" | |
| 35 | |
| 36 """ | |
| 37 from __future__ import absolute_import | |
| 38 | |
| 39 try: | |
| 40 import socks | |
| 41 except ImportError: | |
| 42 import warnings | |
| 43 from ..exceptions import DependencyWarning | |
| 44 | |
| 45 warnings.warn( | |
| 46 ( | |
| 47 "SOCKS support in urllib3 requires the installation of optional " | |
| 48 "dependencies: specifically, PySocks. For more information, see " | |
| 49 "https://urllib3.readthedocs.io/en/latest/contrib.html#socks-proxies" | |
| 50 ), | |
| 51 DependencyWarning, | |
| 52 ) | |
| 53 raise | |
| 54 | |
| 55 from socket import error as SocketError, timeout as SocketTimeout | |
| 56 | |
| 57 from ..connection import HTTPConnection, HTTPSConnection | |
| 58 from ..connectionpool import HTTPConnectionPool, HTTPSConnectionPool | |
| 59 from ..exceptions import ConnectTimeoutError, NewConnectionError | |
| 60 from ..poolmanager import PoolManager | |
| 61 from ..util.url import parse_url | |
| 62 | |
| 63 try: | |
| 64 import ssl | |
| 65 except ImportError: | |
| 66 ssl = None | |
| 67 | |
| 68 | |
| 69 class SOCKSConnection(HTTPConnection): | |
| 70 """ | |
| 71 A plain-text HTTP connection that connects via a SOCKS proxy. | |
| 72 """ | |
| 73 | |
| 74 def __init__(self, *args, **kwargs): | |
| 75 self._socks_options = kwargs.pop("_socks_options") | |
| 76 super(SOCKSConnection, self).__init__(*args, **kwargs) | |
| 77 | |
| 78 def _new_conn(self): | |
| 79 """ | |
| 80 Establish a new connection via the SOCKS proxy. | |
| 81 """ | |
| 82 extra_kw = {} | |
| 83 if self.source_address: | |
| 84 extra_kw["source_address"] = self.source_address | |
| 85 | |
| 86 if self.socket_options: | |
| 87 extra_kw["socket_options"] = self.socket_options | |
| 88 | |
| 89 try: | |
| 90 conn = socks.create_connection( | |
| 91 (self.host, self.port), | |
| 92 proxy_type=self._socks_options["socks_version"], | |
| 93 proxy_addr=self._socks_options["proxy_host"], | |
| 94 proxy_port=self._socks_options["proxy_port"], | |
| 95 proxy_username=self._socks_options["username"], | |
| 96 proxy_password=self._socks_options["password"], | |
| 97 proxy_rdns=self._socks_options["rdns"], | |
| 98 timeout=self.timeout, | |
| 99 **extra_kw | |
| 100 ) | |
| 101 | |
| 102 except SocketTimeout: | |
| 103 raise ConnectTimeoutError( | |
| 104 self, | |
| 105 "Connection to %s timed out. (connect timeout=%s)" | |
| 106 % (self.host, self.timeout), | |
| 107 ) | |
| 108 | |
| 109 except socks.ProxyError as e: | |
| 110 # This is fragile as hell, but it seems to be the only way to raise | |
| 111 # useful errors here. | |
| 112 if e.socket_err: | |
| 113 error = e.socket_err | |
| 114 if isinstance(error, SocketTimeout): | |
| 115 raise ConnectTimeoutError( | |
| 116 self, | |
| 117 "Connection to %s timed out. (connect timeout=%s)" | |
| 118 % (self.host, self.timeout), | |
| 119 ) | |
| 120 else: | |
| 121 raise NewConnectionError( | |
| 122 self, "Failed to establish a new connection: %s" % error | |
| 123 ) | |
| 124 else: | |
| 125 raise NewConnectionError( | |
| 126 self, "Failed to establish a new connection: %s" % e | |
| 127 ) | |
| 128 | |
| 129 except SocketError as e: # Defensive: PySocks should catch all these. | |
| 130 raise NewConnectionError( | |
| 131 self, "Failed to establish a new connection: %s" % e | |
| 132 ) | |
| 133 | |
| 134 return conn | |
| 135 | |
| 136 | |
| 137 # We don't need to duplicate the Verified/Unverified distinction from | |
| 138 # urllib3/connection.py here because the HTTPSConnection will already have been | |
| 139 # correctly set to either the Verified or Unverified form by that module. This | |
| 140 # means the SOCKSHTTPSConnection will automatically be the correct type. | |
| 141 class SOCKSHTTPSConnection(SOCKSConnection, HTTPSConnection): | |
| 142 pass | |
| 143 | |
| 144 | |
| 145 class SOCKSHTTPConnectionPool(HTTPConnectionPool): | |
| 146 ConnectionCls = SOCKSConnection | |
| 147 | |
| 148 | |
| 149 class SOCKSHTTPSConnectionPool(HTTPSConnectionPool): | |
| 150 ConnectionCls = SOCKSHTTPSConnection | |
| 151 | |
| 152 | |
| 153 class SOCKSProxyManager(PoolManager): | |
| 154 """ | |
| 155 A version of the urllib3 ProxyManager that routes connections via the | |
| 156 defined SOCKS proxy. | |
| 157 """ | |
| 158 | |
| 159 pool_classes_by_scheme = { | |
| 160 "http": SOCKSHTTPConnectionPool, | |
| 161 "https": SOCKSHTTPSConnectionPool, | |
| 162 } | |
| 163 | |
| 164 def __init__( | |
| 165 self, | |
| 166 proxy_url, | |
| 167 username=None, | |
| 168 password=None, | |
| 169 num_pools=10, | |
| 170 headers=None, | |
| 171 **connection_pool_kw | |
| 172 ): | |
| 173 parsed = parse_url(proxy_url) | |
| 174 | |
| 175 if username is None and password is None and parsed.auth is not None: | |
| 176 split = parsed.auth.split(":") | |
| 177 if len(split) == 2: | |
| 178 username, password = split | |
| 179 if parsed.scheme == "socks5": | |
| 180 socks_version = socks.PROXY_TYPE_SOCKS5 | |
| 181 rdns = False | |
| 182 elif parsed.scheme == "socks5h": | |
| 183 socks_version = socks.PROXY_TYPE_SOCKS5 | |
| 184 rdns = True | |
| 185 elif parsed.scheme == "socks4": | |
| 186 socks_version = socks.PROXY_TYPE_SOCKS4 | |
| 187 rdns = False | |
| 188 elif parsed.scheme == "socks4a": | |
| 189 socks_version = socks.PROXY_TYPE_SOCKS4 | |
| 190 rdns = True | |
| 191 else: | |
| 192 raise ValueError("Unable to determine SOCKS version from %s" % proxy_url) | |
| 193 | |
| 194 self.proxy_url = proxy_url | |
| 195 | |
| 196 socks_options = { | |
| 197 "socks_version": socks_version, | |
| 198 "proxy_host": parsed.host, | |
| 199 "proxy_port": parsed.port, | |
| 200 "username": username, | |
| 201 "password": password, | |
| 202 "rdns": rdns, | |
| 203 } | |
| 204 connection_pool_kw["_socks_options"] = socks_options | |
| 205 | |
| 206 super(SOCKSProxyManager, self).__init__( | |
| 207 num_pools, headers, **connection_pool_kw | |
| 208 ) | |
| 209 | |
| 210 self.pool_classes_by_scheme = SOCKSProxyManager.pool_classes_by_scheme |
