|
|
@ -4,57 +4,45 @@ |
|
|
|
# This module is part of urllib3 and is released under |
|
|
|
# the MIT License: http://www.opensource.org/licenses/mit-license.php |
|
|
|
|
|
|
|
import logging |
|
|
|
import socket |
|
|
|
import errno |
|
|
|
import logging |
|
|
|
|
|
|
|
from socket import error as SocketError, timeout as SocketTimeout |
|
|
|
from .util import resolve_cert_reqs, resolve_ssl_version, assert_fingerprint |
|
|
|
|
|
|
|
try: # Python 3 |
|
|
|
from http.client import HTTPConnection, HTTPException |
|
|
|
from http.client import HTTP_PORT, HTTPS_PORT |
|
|
|
except ImportError: |
|
|
|
from httplib import HTTPConnection, HTTPException |
|
|
|
from httplib import HTTP_PORT, HTTPS_PORT |
|
|
|
import socket |
|
|
|
|
|
|
|
try: # Python 3 |
|
|
|
from queue import LifoQueue, Empty, Full |
|
|
|
except ImportError: |
|
|
|
from Queue import LifoQueue, Empty, Full |
|
|
|
import Queue as _ # Platform-specific: Windows |
|
|
|
|
|
|
|
|
|
|
|
try: # Compiled with SSL? |
|
|
|
HTTPSConnection = object |
|
|
|
BaseSSLError = None |
|
|
|
ssl = None |
|
|
|
|
|
|
|
try: # Python 3 |
|
|
|
from http.client import HTTPSConnection |
|
|
|
except ImportError: |
|
|
|
from httplib import HTTPSConnection |
|
|
|
|
|
|
|
import ssl |
|
|
|
BaseSSLError = ssl.SSLError |
|
|
|
|
|
|
|
except (ImportError, AttributeError): # Platform-specific: No SSL. |
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
from .request import RequestMethods |
|
|
|
from .response import HTTPResponse |
|
|
|
from .util import get_host, is_connection_dropped, ssl_wrap_socket |
|
|
|
from .exceptions import ( |
|
|
|
ClosedPoolError, |
|
|
|
ConnectTimeoutError, |
|
|
|
EmptyPoolError, |
|
|
|
HostChangedError, |
|
|
|
MaxRetryError, |
|
|
|
SSLError, |
|
|
|
TimeoutError, |
|
|
|
ReadTimeoutError, |
|
|
|
ProxyError, |
|
|
|
) |
|
|
|
|
|
|
|
from .packages.ssl_match_hostname import match_hostname, CertificateError |
|
|
|
from .packages.ssl_match_hostname import CertificateError |
|
|
|
from .packages import six |
|
|
|
from .connection import ( |
|
|
|
DummyConnection, |
|
|
|
HTTPConnection, HTTPSConnection, VerifiedHTTPSConnection, |
|
|
|
HTTPException, BaseSSLError, |
|
|
|
) |
|
|
|
from .request import RequestMethods |
|
|
|
from .response import HTTPResponse |
|
|
|
from .util import ( |
|
|
|
assert_fingerprint, |
|
|
|
get_host, |
|
|
|
is_connection_dropped, |
|
|
|
Timeout, |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
xrange = six.moves.xrange |
|
|
@ -64,56 +52,11 @@ log = logging.getLogger(__name__) |
|
|
|
_Default = object() |
|
|
|
|
|
|
|
port_by_scheme = { |
|
|
|
'http': HTTP_PORT, |
|
|
|
'https': HTTPS_PORT, |
|
|
|
'http': 80, |
|
|
|
'https': 443, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
## Connection objects (extension of httplib) |
|
|
|
|
|
|
|
class VerifiedHTTPSConnection(HTTPSConnection): |
|
|
|
""" |
|
|
|
Based on httplib.HTTPSConnection but wraps the socket with |
|
|
|
SSL certification. |
|
|
|
""" |
|
|
|
cert_reqs = None |
|
|
|
ca_certs = None |
|
|
|
ssl_version = None |
|
|
|
|
|
|
|
def set_cert(self, key_file=None, cert_file=None, |
|
|
|
cert_reqs=None, ca_certs=None, |
|
|
|
assert_hostname=None, assert_fingerprint=None): |
|
|
|
|
|
|
|
self.key_file = key_file |
|
|
|
self.cert_file = cert_file |
|
|
|
self.cert_reqs = cert_reqs |
|
|
|
self.ca_certs = ca_certs |
|
|
|
self.assert_hostname = assert_hostname |
|
|
|
self.assert_fingerprint = assert_fingerprint |
|
|
|
|
|
|
|
def connect(self): |
|
|
|
# Add certificate verification |
|
|
|
sock = socket.create_connection((self.host, self.port), self.timeout) |
|
|
|
|
|
|
|
resolved_cert_reqs = resolve_cert_reqs(self.cert_reqs) |
|
|
|
resolved_ssl_version = resolve_ssl_version(self.ssl_version) |
|
|
|
|
|
|
|
# Wrap socket using verification with the root certs in |
|
|
|
# trusted_root_certs |
|
|
|
self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file, |
|
|
|
cert_reqs=resolved_cert_reqs, |
|
|
|
ca_certs=self.ca_certs, |
|
|
|
server_hostname=self.host, |
|
|
|
ssl_version=resolved_ssl_version) |
|
|
|
|
|
|
|
if resolved_cert_reqs != ssl.CERT_NONE: |
|
|
|
if self.assert_fingerprint: |
|
|
|
assert_fingerprint(self.sock.getpeercert(binary_form=True), |
|
|
|
self.assert_fingerprint) |
|
|
|
else: |
|
|
|
match_hostname(self.sock.getpeercert(), |
|
|
|
self.assert_hostname or self.host) |
|
|
|
|
|
|
|
## Pool objects |
|
|
|
|
|
|
|
class ConnectionPool(object): |
|
|
@ -126,6 +69,9 @@ class ConnectionPool(object): |
|
|
|
QueueCls = LifoQueue |
|
|
|
|
|
|
|
def __init__(self, host, port=None): |
|
|
|
# httplib doesn't like it when we include brackets in ipv6 addresses |
|
|
|
host = host.strip('[]') |
|
|
|
|
|
|
|
self.host = host |
|
|
|
self.port = port |
|
|
|
|
|
|
@ -133,6 +79,8 @@ class ConnectionPool(object): |
|
|
|
return '%s(host=%r, port=%r)' % (type(self).__name__, |
|
|
|
self.host, self.port) |
|
|
|
|
|
|
|
# This is taken from http://hg.python.org/cpython/file/7aaba721ebc0/Lib/socket.py#l252 |
|
|
|
_blocking_errnos = set([errno.EAGAIN, errno.EWOULDBLOCK]) |
|
|
|
|
|
|
|
class HTTPConnectionPool(ConnectionPool, RequestMethods): |
|
|
|
""" |
|
|
@ -151,9 +99,15 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): |
|
|
|
as a valid HTTP/1.0 or 1.1 status line, passed into |
|
|
|
:class:`httplib.HTTPConnection`. |
|
|
|
|
|
|
|
.. note:: |
|
|
|
Only works in Python 2. This parameter is ignored in Python 3. |
|
|
|
|
|
|
|
:param timeout: |
|
|
|
Socket timeout for each individual connection, can be a float. None |
|
|
|
disables timeout. |
|
|
|
Socket timeout in seconds for each individual connection. This can |
|
|
|
be a float or integer, which sets the timeout for the HTTP request, |
|
|
|
or an instance of :class:`urllib3.util.Timeout` which gives you more |
|
|
|
fine-grained control over request timeouts. After the constructor has |
|
|
|
been parsed, this is always a `urllib3.util.Timeout` object. |
|
|
|
|
|
|
|
:param maxsize: |
|
|
|
Number of connections to save that can be reused. More than 1 is useful |
|
|
@ -171,20 +125,40 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): |
|
|
|
:param headers: |
|
|
|
Headers to include with all requests, unless other headers are given |
|
|
|
explicitly. |
|
|
|
|
|
|
|
:param _proxy: |
|
|
|
Parsed proxy URL, should not be used directly, instead, see |
|
|
|
:class:`urllib3.connectionpool.ProxyManager`" |
|
|
|
|
|
|
|
:param _proxy_headers: |
|
|
|
A dictionary with proxy headers, should not be used directly, |
|
|
|
instead, see :class:`urllib3.connectionpool.ProxyManager`" |
|
|
|
""" |
|
|
|
|
|
|
|
scheme = 'http' |
|
|
|
ConnectionCls = HTTPConnection |
|
|
|
|
|
|
|
def __init__(self, host, port=None, strict=False, timeout=None, maxsize=1, |
|
|
|
block=False, headers=None): |
|
|
|
def __init__(self, host, port=None, strict=False, |
|
|
|
timeout=Timeout.DEFAULT_TIMEOUT, maxsize=1, block=False, |
|
|
|
headers=None, _proxy=None, _proxy_headers=None): |
|
|
|
ConnectionPool.__init__(self, host, port) |
|
|
|
RequestMethods.__init__(self, headers) |
|
|
|
|
|
|
|
self.strict = strict |
|
|
|
|
|
|
|
# This is for backwards compatibility and can be removed once a timeout |
|
|
|
# can only be set to a Timeout object |
|
|
|
if not isinstance(timeout, Timeout): |
|
|
|
timeout = Timeout.from_float(timeout) |
|
|
|
|
|
|
|
self.timeout = timeout |
|
|
|
|
|
|
|
self.pool = self.QueueCls(maxsize) |
|
|
|
self.block = block |
|
|
|
|
|
|
|
self.proxy = _proxy |
|
|
|
self.proxy_headers = _proxy_headers or {} |
|
|
|
|
|
|
|
# Fill the queue up so that doing get() on it will block properly |
|
|
|
for _ in xrange(maxsize): |
|
|
|
self.pool.put(None) |
|
|
@ -200,9 +174,14 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): |
|
|
|
self.num_connections += 1 |
|
|
|
log.info("Starting new HTTP connection (%d): %s" % |
|
|
|
(self.num_connections, self.host)) |
|
|
|
return HTTPConnection(host=self.host, |
|
|
|
port=self.port, |
|
|
|
strict=self.strict) |
|
|
|
|
|
|
|
extra_params = {} |
|
|
|
if not six.PY3: # Python 2 |
|
|
|
extra_params['strict'] = self.strict |
|
|
|
|
|
|
|
return self.ConnectionCls(host=self.host, port=self.port, |
|
|
|
timeout=self.timeout.connect_timeout, |
|
|
|
**extra_params) |
|
|
|
|
|
|
|
def _get_conn(self, timeout=None): |
|
|
|
""" |
|
|
@ -263,31 +242,100 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): |
|
|
|
% self.host) |
|
|
|
|
|
|
|
# Connection never got put back into the pool, close it. |
|
|
|
conn.close() |
|
|
|
if conn: |
|
|
|
conn.close() |
|
|
|
|
|
|
|
def _get_timeout(self, timeout): |
|
|
|
""" Helper that always returns a :class:`urllib3.util.Timeout` """ |
|
|
|
if timeout is _Default: |
|
|
|
return self.timeout.clone() |
|
|
|
|
|
|
|
if isinstance(timeout, Timeout): |
|
|
|
return timeout.clone() |
|
|
|
else: |
|
|
|
# User passed us an int/float. This is for backwards compatibility, |
|
|
|
# can be removed later |
|
|
|
return Timeout.from_float(timeout) |
|
|
|
|
|
|
|
def _make_request(self, conn, method, url, timeout=_Default, |
|
|
|
**httplib_request_kw): |
|
|
|
""" |
|
|
|
Perform a request on a given httplib connection object taken from our |
|
|
|
pool. |
|
|
|
|
|
|
|
:param conn: |
|
|
|
a connection from one of our connection pools |
|
|
|
|
|
|
|
:param timeout: |
|
|
|
Socket timeout in seconds for the request. This can be a |
|
|
|
float or integer, which will set the same timeout value for |
|
|
|
the socket connect and the socket read, or an instance of |
|
|
|
:class:`urllib3.util.Timeout`, which gives you more fine-grained |
|
|
|
control over your timeouts. |
|
|
|
""" |
|
|
|
self.num_requests += 1 |
|
|
|
|
|
|
|
if timeout is _Default: |
|
|
|
timeout = self.timeout |
|
|
|
timeout_obj = self._get_timeout(timeout) |
|
|
|
|
|
|
|
conn.timeout = timeout # This only does anything in Py26+ |
|
|
|
conn.request(method, url, **httplib_request_kw) |
|
|
|
try: |
|
|
|
timeout_obj.start_connect() |
|
|
|
conn.timeout = timeout_obj.connect_timeout |
|
|
|
# conn.request() calls httplib.*.request, not the method in |
|
|
|
# urllib3.request. It also calls makefile (recv) on the socket. |
|
|
|
conn.request(method, url, **httplib_request_kw) |
|
|
|
except SocketTimeout: |
|
|
|
raise ConnectTimeoutError( |
|
|
|
self, "Connection to %s timed out. (connect timeout=%s)" % |
|
|
|
(self.host, timeout_obj.connect_timeout)) |
|
|
|
|
|
|
|
# Reset the timeout for the recv() on the socket |
|
|
|
read_timeout = timeout_obj.read_timeout |
|
|
|
|
|
|
|
# App Engine doesn't have a sock attr |
|
|
|
if hasattr(conn, 'sock'): |
|
|
|
# In Python 3 socket.py will catch EAGAIN and return None when you |
|
|
|
# try and read into the file pointer created by http.client, which |
|
|
|
# instead raises a BadStatusLine exception. Instead of catching |
|
|
|
# the exception and assuming all BadStatusLine exceptions are read |
|
|
|
# timeouts, check for a zero timeout before making the request. |
|
|
|
if read_timeout == 0: |
|
|
|
raise ReadTimeoutError( |
|
|
|
self, url, |
|
|
|
"Read timed out. (read timeout=%s)" % read_timeout) |
|
|
|
if read_timeout is Timeout.DEFAULT_TIMEOUT: |
|
|
|
conn.sock.settimeout(socket.getdefaulttimeout()) |
|
|
|
else: # None or a value |
|
|
|
conn.sock.settimeout(read_timeout) |
|
|
|
|
|
|
|
# Receive the response from the server |
|
|
|
try: |
|
|
|
try: # Python 2.7+, use buffering of HTTP responses |
|
|
|
httplib_response = conn.getresponse(buffering=True) |
|
|
|
except TypeError: # Python 2.6 and older |
|
|
|
httplib_response = conn.getresponse() |
|
|
|
except SocketTimeout: |
|
|
|
raise ReadTimeoutError( |
|
|
|
self, url, "Read timed out. (read timeout=%s)" % read_timeout) |
|
|
|
|
|
|
|
# Set timeout |
|
|
|
sock = getattr(conn, 'sock', False) # AppEngine doesn't have sock attr. |
|
|
|
if sock: |
|
|
|
sock.settimeout(timeout) |
|
|
|
except BaseSSLError as e: |
|
|
|
# Catch possible read timeouts thrown as SSL errors. If not the |
|
|
|
# case, rethrow the original. We need to do this because of: |
|
|
|
# http://bugs.python.org/issue10272 |
|
|
|
if 'timed out' in str(e) or \ |
|
|
|
'did not complete (read)' in str(e): # Python 2.6 |
|
|
|
raise ReadTimeoutError(self, url, "Read timed out.") |
|
|
|
|
|
|
|
try: # Python 2.7+, use buffering of HTTP responses |
|
|
|
httplib_response = conn.getresponse(buffering=True) |
|
|
|
except TypeError: # Python 2.6 and older |
|
|
|
httplib_response = conn.getresponse() |
|
|
|
raise |
|
|
|
|
|
|
|
except SocketError as e: # Platform-specific: Python 2 |
|
|
|
# See the above comment about EAGAIN in Python 3. In Python 2 we |
|
|
|
# have to specifically catch it and throw the timeout error |
|
|
|
if e.errno in _blocking_errnos: |
|
|
|
raise ReadTimeoutError( |
|
|
|
self, url, |
|
|
|
"Read timed out. (read timeout=%s)" % read_timeout) |
|
|
|
|
|
|
|
raise |
|
|
|
|
|
|
|
# AppEngine doesn't have a version attr. |
|
|
|
http_version = getattr(conn, '_http_vsn_str', 'HTTP/?') |
|
|
@ -367,7 +415,7 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): |
|
|
|
|
|
|
|
:param redirect: |
|
|
|
If True, automatically handle redirects (status codes 301, 302, |
|
|
|
303, 307). Each redirect counts as a retry. |
|
|
|
303, 307, 308). Each redirect counts as a retry. |
|
|
|
|
|
|
|
:param assert_same_host: |
|
|
|
If ``True``, will make sure that the host of the pool requests is |
|
|
@ -375,7 +423,9 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): |
|
|
|
use the pool on an HTTP proxy and request foreign hosts. |
|
|
|
|
|
|
|
:param timeout: |
|
|
|
If specified, overrides the default timeout for this one request. |
|
|
|
If specified, overrides the default timeout for this one |
|
|
|
request. It may be a float (in seconds) or an instance of |
|
|
|
:class:`urllib3.util.Timeout`. |
|
|
|
|
|
|
|
:param pool_timeout: |
|
|
|
If set and the pool is set to block=True, then this method will |
|
|
@ -402,22 +452,22 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): |
|
|
|
if retries < 0: |
|
|
|
raise MaxRetryError(self, url) |
|
|
|
|
|
|
|
if timeout is _Default: |
|
|
|
timeout = self.timeout |
|
|
|
|
|
|
|
if release_conn is None: |
|
|
|
release_conn = response_kw.get('preload_content', True) |
|
|
|
|
|
|
|
# Check host |
|
|
|
if assert_same_host and not self.is_same_host(url): |
|
|
|
host = "%s://%s" % (self.scheme, self.host) |
|
|
|
if self.port: |
|
|
|
host = "%s:%d" % (host, self.port) |
|
|
|
|
|
|
|
raise HostChangedError(self, url, retries - 1) |
|
|
|
|
|
|
|
conn = None |
|
|
|
|
|
|
|
# Merge the proxy headers. Only do this in HTTP. We have to copy the |
|
|
|
# headers dict so we can safely change it without those changes being |
|
|
|
# reflected in anyone else's copy. |
|
|
|
if self.scheme == 'http': |
|
|
|
headers = headers.copy() |
|
|
|
headers.update(self.proxy_headers) |
|
|
|
|
|
|
|
try: |
|
|
|
# Request a connection from the queue |
|
|
|
conn = self._get_conn(timeout=pool_timeout) |
|
|
@ -444,27 +494,31 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): |
|
|
|
# ``response.release_conn()`` is called (implicitly by |
|
|
|
# ``response.read()``) |
|
|
|
|
|
|
|
except Empty as e: |
|
|
|
except Empty: |
|
|
|
# Timed out by queue |
|
|
|
raise TimeoutError(self, url, |
|
|
|
"Request timed out. (pool_timeout=%s)" % |
|
|
|
pool_timeout) |
|
|
|
|
|
|
|
except SocketTimeout as e: |
|
|
|
# Timed out by socket |
|
|
|
raise TimeoutError(self, url, |
|
|
|
"Request timed out. (timeout=%s)" % |
|
|
|
timeout) |
|
|
|
raise EmptyPoolError(self, "No pool connections are available.") |
|
|
|
|
|
|
|
except BaseSSLError as e: |
|
|
|
# SSL certificate error |
|
|
|
raise SSLError(e) |
|
|
|
|
|
|
|
except CertificateError as e: |
|
|
|
# Name mismatch |
|
|
|
raise SSLError(e) |
|
|
|
|
|
|
|
except TimeoutError as e: |
|
|
|
# Connection broken, discard. |
|
|
|
conn = None |
|
|
|
# Save the error off for retry logic. |
|
|
|
err = e |
|
|
|
|
|
|
|
if retries == 0: |
|
|
|
raise |
|
|
|
|
|
|
|
except (HTTPException, SocketError) as e: |
|
|
|
if isinstance(e, SocketError) and self.proxy is not None: |
|
|
|
raise ProxyError('Cannot connect to proxy. ' |
|
|
|
'Socket error: %s.' % e) |
|
|
|
|
|
|
|
# Connection broken, discard. It will be replaced next _get_conn(). |
|
|
|
conn = None |
|
|
|
# This is necessary so we can access e below |
|
|
@ -513,6 +567,7 @@ class HTTPSConnectionPool(HTTPConnectionPool): |
|
|
|
|
|
|
|
:class:`.VerifiedHTTPSConnection` uses one of ``assert_fingerprint``, |
|
|
|
``assert_hostname`` and ``host`` in this order to verify connections. |
|
|
|
If ``assert_hostname`` is False, no verification is done. |
|
|
|
|
|
|
|
The ``key_file``, ``cert_file``, ``cert_reqs``, ``ca_certs`` and |
|
|
|
``ssl_version`` are only used if :mod:`ssl` is available and are fed into |
|
|
@ -521,17 +576,18 @@ class HTTPSConnectionPool(HTTPConnectionPool): |
|
|
|
""" |
|
|
|
|
|
|
|
scheme = 'https' |
|
|
|
ConnectionCls = HTTPSConnection |
|
|
|
|
|
|
|
def __init__(self, host, port=None, |
|
|
|
strict=False, timeout=None, maxsize=1, |
|
|
|
block=False, headers=None, |
|
|
|
_proxy=None, _proxy_headers=None, |
|
|
|
key_file=None, cert_file=None, cert_reqs=None, |
|
|
|
ca_certs=None, ssl_version=None, |
|
|
|
assert_hostname=None, assert_fingerprint=None): |
|
|
|
|
|
|
|
HTTPConnectionPool.__init__(self, host, port, |
|
|
|
strict, timeout, maxsize, |
|
|
|
block, headers) |
|
|
|
HTTPConnectionPool.__init__(self, host, port, strict, timeout, maxsize, |
|
|
|
block, headers, _proxy, _proxy_headers) |
|
|
|
self.key_file = key_file |
|
|
|
self.cert_file = cert_file |
|
|
|
self.cert_reqs = cert_reqs |
|
|
@ -540,6 +596,34 @@ class HTTPSConnectionPool(HTTPConnectionPool): |
|
|
|
self.assert_hostname = assert_hostname |
|
|
|
self.assert_fingerprint = assert_fingerprint |
|
|
|
|
|
|
|
def _prepare_conn(self, conn): |
|
|
|
""" |
|
|
|
Prepare the ``connection`` for :meth:`urllib3.util.ssl_wrap_socket` |
|
|
|
and establish the tunnel if proxy is used. |
|
|
|
""" |
|
|
|
|
|
|
|
if isinstance(conn, VerifiedHTTPSConnection): |
|
|
|
conn.set_cert(key_file=self.key_file, |
|
|
|
cert_file=self.cert_file, |
|
|
|
cert_reqs=self.cert_reqs, |
|
|
|
ca_certs=self.ca_certs, |
|
|
|
assert_hostname=self.assert_hostname, |
|
|
|
assert_fingerprint=self.assert_fingerprint) |
|
|
|
conn.ssl_version = self.ssl_version |
|
|
|
|
|
|
|
if self.proxy is not None: |
|
|
|
# Python 2.7+ |
|
|
|
try: |
|
|
|
set_tunnel = conn.set_tunnel |
|
|
|
except AttributeError: # Platform-specific: Python 2.6 |
|
|
|
set_tunnel = conn._set_tunnel |
|
|
|
set_tunnel(self.host, self.port, self.proxy_headers) |
|
|
|
# Establish tunnel connection early, because otherwise httplib |
|
|
|
# would improperly set Host: header to proxy's IP:port. |
|
|
|
conn.connect() |
|
|
|
|
|
|
|
return conn |
|
|
|
|
|
|
|
def _new_conn(self): |
|
|
|
""" |
|
|
|
Return a fresh :class:`httplib.HTTPSConnection`. |
|
|
@ -548,26 +632,26 @@ class HTTPSConnectionPool(HTTPConnectionPool): |
|
|
|
log.info("Starting new HTTPS connection (%d): %s" |
|
|
|
% (self.num_connections, self.host)) |
|
|
|
|
|
|
|
if not ssl: # Platform-specific: Python compiled without +ssl |
|
|
|
if not HTTPSConnection or HTTPSConnection is object: |
|
|
|
raise SSLError("Can't connect to HTTPS URL because the SSL " |
|
|
|
"module is not available.") |
|
|
|
if not self.ConnectionCls or self.ConnectionCls is DummyConnection: |
|
|
|
# Platform-specific: Python without ssl |
|
|
|
raise SSLError("Can't connect to HTTPS URL because the SSL " |
|
|
|
"module is not available.") |
|
|
|
|
|
|
|
return HTTPSConnection(host=self.host, |
|
|
|
port=self.port, |
|
|
|
strict=self.strict) |
|
|
|
actual_host = self.host |
|
|
|
actual_port = self.port |
|
|
|
if self.proxy is not None: |
|
|
|
actual_host = self.proxy.host |
|
|
|
actual_port = self.proxy.port |
|
|
|
|
|
|
|
connection = VerifiedHTTPSConnection(host=self.host, |
|
|
|
port=self.port, |
|
|
|
strict=self.strict) |
|
|
|
connection.set_cert(key_file=self.key_file, cert_file=self.cert_file, |
|
|
|
cert_reqs=self.cert_reqs, ca_certs=self.ca_certs, |
|
|
|
assert_hostname=self.assert_hostname, |
|
|
|
assert_fingerprint=self.assert_fingerprint) |
|
|
|
extra_params = {} |
|
|
|
if not six.PY3: # Python 2 |
|
|
|
extra_params['strict'] = self.strict |
|
|
|
|
|
|
|
connection.ssl_version = self.ssl_version |
|
|
|
conn = self.ConnectionCls(host=actual_host, port=actual_port, |
|
|
|
timeout=self.timeout.connect_timeout, |
|
|
|
**extra_params) |
|
|
|
|
|
|
|
return connection |
|
|
|
return self._prepare_conn(conn) |
|
|
|
|
|
|
|
|
|
|
|
def connection_from_url(url, **kw): |
|
|
|