1from __future__
import absolute_import
7from ._collections
import RecentlyUsedContainer
8from .connectionpool
import HTTPConnectionPool, HTTPSConnectionPool, port_by_scheme
9from .exceptions
import (
13 ProxySchemeUnsupported,
16from .packages
import six
18from .request
import RequestMethods
19from .
util.proxy import connection_requires_http_tunnel
23__all__ = [
"PoolManager",
"ProxyManager",
"proxy_from_url"]
66 "key_assert_hostname",
67 "key_assert_fingerprint",
68 "key_server_hostname",
75_proxy_config_fields = (
"ssl_context",
"use_forwarding_for_https")
81 Create a pool key out of a request context dictionary.
83 According to RFC 3986, both the scheme and host are case-insensitive.
84 Therefore, this function normalizes both before constructing the pool
85 key for an HTTPS request. If you wish to change this behaviour, provide
86 alternate callables to ``key_fn_by_scheme``.
89 The class to use when constructing the key. This should be a namedtuple
90 with the ``scheme`` and ``host`` keys at a minimum.
91 :type key_class: namedtuple
92 :param request_context:
93 A dictionary-like object that contain the context for a request.
94 :type request_context: dict
96 :return: A namedtuple that can be used as a connection pool key.
101 context[
"scheme"] = context[
"scheme"].
lower()
102 context[
"host"] = context[
"host"].
lower()
105 for key
in (
"headers",
"_proxy_headers",
"_socks_options"):
106 if key
in context
and context[key]
is not None:
107 context[key] =
frozenset(context[key].items())
112 if socket_opts
is not None:
113 context[
"socket_options"] = tuple(socket_opts)
122 if field
not in context:
123 context[field] =
None
137pool_classes_by_scheme = {
"http": HTTPConnectionPool,
"https": HTTPSConnectionPool}
142 Allows for arbitrary requests while transparently keeping track of
143 necessary connection pools for you.
146 Number of connection pools to cache before discarding the least
150 Headers to include with all requests, unless other headers are given
153 :param \\**connection_pool_kw:
154 Additional parameters are used to create fresh
155 :class:`urllib3.connectionpool.ConnectionPool` instances.
159 >>> manager = PoolManager(num_pools=2)
160 >>> r = manager.request('GET', 'http://google.com/')
161 >>> r = manager.request('GET', 'http://google.com/mail')
162 >>> r = manager.request('GET', 'http://yahoo.com/')
163 >>> len(manager.pools)
171 def __init__(self, num_pools=10, headers=None, **connection_pool_kw):
189 def _new_pool(self, scheme, host, port, request_context=None):
191 Create a new :class:`urllib3.connectionpool.ConnectionPool` based on host, port, scheme, and
192 any additional pool keyword arguments.
194 If ``request_context`` is provided, it is provided as keyword arguments
195 to the pool class used. This method is used to actually create the
196 connection pools handed out by :meth:`connection_from_url` and
197 companion methods. It is intended to be overridden for customization.
200 if request_context
is None:
207 for key
in (
"scheme",
"host",
"port"):
211 for kw
in SSL_KEYWORDS:
214 return pool_cls(host, port, **request_context)
218 Empty our store of pools and direct them all to close.
220 This will not affect in-flight connections, but they will not be
221 re-used after completion.
227 Get a :class:`urllib3.connectionpool.ConnectionPool` based on the host, port, and scheme.
229 If ``port`` isn't given, it will be derived from the ``scheme`` using
230 ``urllib3.connectionpool.port_by_scheme``. If ``pool_kwargs`` is
231 provided, it is merged with the instance's ``connection_pool_kw``
232 variable and used to create the new connection pool, if one is
240 request_context[
"scheme"] = scheme
or "http"
243 request_context[
"port"] = port
244 request_context[
"host"] = host
250 Get a :class:`urllib3.connectionpool.ConnectionPool` based on the request context.
252 ``request_context`` must at least contain the ``scheme`` key and its
253 value must be a key in ``key_fn_by_scheme`` instance variable.
255 scheme = request_context[
"scheme"].
lower()
257 if not pool_key_constructor:
265 Get a :class:`urllib3.connectionpool.ConnectionPool` based on the provided pool key.
267 ``pool_key`` should be a namedtuple that only contains immutable
268 objects. At a minimum it must have the ``scheme``, ``host``, and
271 with self.
pools.lock:
274 pool = self.
pools.get(pool_key)
279 scheme = request_context[
"scheme"]
280 host = request_context[
"host"]
281 port = request_context[
"port"]
282 pool = self.
_new_pool(scheme, host, port, request_context=request_context)
283 self.
pools[pool_key] = pool
287 def connection_from_url(self, url, pool_kwargs=None):
289 Similar to :func:`urllib3.connectionpool.connection_from_url`.
291 If ``pool_kwargs`` is not provided and a new pool needs to be
292 constructed, ``self.connection_pool_kw`` is used to initialize
293 the :class:`urllib3.connectionpool.ConnectionPool`. If ``pool_kwargs``
294 is provided, it is used instead. Note that if a new pool does not
295 need to be created for the request, the provided ``pool_kwargs`` are
305 Merge a dictionary of override values for self.connection_pool_kw.
307 This does not modify self.connection_pool_kw and returns a new dict.
308 Any keys in the override dictionary with a value of ``None`` are
309 removed from the merged dictionary.
316 del base_pool_kwargs[key]
320 base_pool_kwargs[key] = value
321 return base_pool_kwargs
325 Indicates if the proxy requires the complete destination URL in the
326 request. Normally this is only needed when not using an HTTP CONNECT
329 if self.
proxy is None:
332 return not connection_requires_http_tunnel(
338 Validates that were not attempting to do TLS in TLS connections on
339 Python2 or with unsupported SSL implementations.
341 if self.
proxy is None or url_scheme !=
"https":
344 if self.
proxy.scheme !=
"https":
349 "Contacting HTTPS destinations through HTTPS proxies "
350 "'via CONNECT tunnels' is not supported in Python 2"
353 def urlopen(self, method, url, redirect=True, **kw):
355 Same as :meth:`urllib3.HTTPConnectionPool.urlopen`
356 with custom cross-host redirect logic and only sends the request-uri
357 portion of the ``url``.
359 The given ``url`` parameter must be absolute, such that an appropriate
360 :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it.
367 kw[
"assert_same_host"] =
False
368 kw[
"redirect"] =
False
370 if "headers" not in kw:
371 kw[
"headers"] = self.
headers.copy()
379 if not redirect_location:
383 redirect_location = urljoin(url, redirect_location)
389 retries =
kw.get(
"retries")
400 for header
in headers:
402 kw[
"headers"].pop(header,
None)
406 except MaxRetryError:
412 kw[
"retries"] = retries
413 kw[
"redirect"] = redirect
415 log.info(
"Redirecting %s -> %s", url, redirect_location)
423 Behaves just like :class:`PoolManager`, but sends all requests through
424 the defined proxy, using the CONNECT method for HTTPS URLs.
427 The URL of the proxy to be used.
429 :param proxy_headers:
430 A dictionary containing headers that will be sent to the proxy. In case
431 of HTTP they are being sent with each request, while in the
432 HTTPS/CONNECT case they are sent only once. Could be used for proxy
435 :param proxy_ssl_context:
436 The proxy SSL context is used to establish the TLS connection to the
437 proxy when using HTTPS proxies.
439 :param use_forwarding_for_https:
440 (Defaults to False) If set to True will forward requests to the HTTPS
441 proxy to be made on behalf of the client instead of creating a TLS
442 tunnel via the CONNECT method. **Enabling this flag means that request
443 and response headers and content will be visible from the HTTPS proxy**
444 whereas tunneling keeps request and response headers and content
445 private. IP address, target hostname, SNI, and port are always visible
446 to an HTTPS proxy even when this flag is disabled.
449 >>> proxy = urllib3.ProxyManager('http://localhost:3128/')
450 >>> r1 = proxy.request('GET', 'http://google.com/')
451 >>> r2 = proxy.request('GET', 'http://httpbin.org/')
454 >>> r3 = proxy.request('GET', 'https://httpbin.org/')
455 >>> r4 = proxy.request('GET', 'https://twitter.com/')
467 proxy_ssl_context=None,
468 use_forwarding_for_https=False,
473 proxy_url =
"%s://%s:%i" % (
478 proxy = parse_url(proxy_url)
492 connection_pool_kw[
"_proxy"] = self.
proxyproxy
496 super(ProxyManager, self).
__init__(num_pools, headers, **connection_pool_kw)
499 if scheme ==
"https":
501 host, port, scheme, pool_kwargs=pool_kwargs
510 Sets headers needed by proxies: specifically, the Accept and Host
511 headers. Only sets headers not provided by the user.
513 headers_ = {
"Accept":
"*/*"}
515 netloc = parse_url(url).netloc
517 headers_[
"Host"] = netloc
523 def urlopen(self, method, url, redirect=True, **kw):
524 "Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute."
533 return super(ProxyManager, self).urlopen(method, url, redirect=redirect, **kw)
536def proxy_from_url(url, **kw):
_validate_proxy_scheme_url_selection(self, url_scheme)
_new_pool(self, scheme, host, port, request_context=None)
__init__(self, num_pools=10, headers=None, **connection_pool_kw)
connection_from_pool_key(self, pool_key, request_context=None)
connection_from_context(self, request_context)
_proxy_requires_url_absolute_form(self, parsed_url)
__exit__(self, exc_type, exc_val, exc_tb)
urlopen(self, method, url, redirect=True, **kw)
_merge_pool_kwargs(self, override)
connection_from_host(self, host, port=None, scheme="http", pool_kwargs=None)
__init__(self, proxy_url, num_pools=10, headers=None, proxy_headers=None, proxy_ssl_context=None, use_forwarding_for_https=False, **connection_pool_kw)
_set_proxy_headers(self, url, headers=None)
connection_from_host(self, host, port=None, scheme="http", pool_kwargs=None)
urlopen(self, method, url, body=None, headers=None, encode_multipart=True, multipart_boundary=None, **kw)
_default_key_normalizer(key_class, request_context)