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 |