9
9
from socket import timeout as SocketTimeout
12
12
from http.client import HTTPConnection as _HTTPConnection, HTTPException
13
13
except ImportError:
14
14
from httplib import HTTPConnection as _HTTPConnection, HTTPException
16
17
class DummyConnection(object):
17
18
"Used to detect a failed ConnectionCls import."
20
try: # Compiled with SSL?
22
try: # Compiled with SSL?
23
HTTPSConnection = DummyConnection
25
BaseSSLError = ssl.SSLError
26
except (ImportError, AttributeError): # Platform-specific: No SSL.
22
HTTPSConnection = DummyConnection
24
29
class BaseSSLError(BaseException):
28
from http.client import HTTPSConnection as _HTTPSConnection
30
from httplib import HTTPSConnection as _HTTPSConnection
33
BaseSSLError = ssl.SSLError
35
except (ImportError, AttributeError): # Platform-specific: No SSL.
38
33
from .exceptions import (
39
34
ConnectTimeoutError,
59
54
Based on httplib.HTTPConnection but provides an extra constructor
60
55
backwards-compatibility layer between older and newer Pythons.
57
Additional keyword parameters are used to configure attributes of the connection.
58
Accepted parameters include:
60
- ``strict``: See the documentation on :class:`urllib3.connectionpool.HTTPConnectionPool`
61
- ``source_address``: Set the source address for the current connection.
63
.. note:: This is ignored for Python 2.6. It is only applied for 2.7 and 3.x
65
- ``socket_options``: Set specific options on the underlying socket. If not specified, then
66
defaults are loaded from ``HTTPConnection.default_socket_options`` which includes disabling
67
Nagle's algorithm (sets TCP_NODELAY to 1) unless the connection is behind a proxy.
69
For example, if you wish to enable TCP Keep Alive in addition to the defaults,
72
HTTPConnection.default_socket_options + [
73
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
76
Or you may want to disable the defaults by passing an empty list (e.g., ``[]``).
63
79
default_port = port_by_scheme['http']
65
# By default, disable Nagle's Algorithm.
81
#: Disable Nagle's algorithm by default.
82
#: ``[(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]``
83
default_socket_options = [(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]
68
85
def __init__(self, *args, **kw):
69
86
if six.PY3: # Python 3
74
91
# Pre-set source_address in case we have an older Python like 2.6.
75
92
self.source_address = kw.get('source_address')
94
#: The socket options provided by the user. If no options are
95
#: provided, we use the default options.
96
self.socket_options = kw.pop('socket_options', self.default_socket_options)
77
98
# Superclass also sets self.source_address in Python 2.7+.
78
_HTTPConnection.__init__(self, *args, **kw)
99
_HTTPConnection.__init__(self, *args, **kw)
80
101
def _new_conn(self):
81
102
""" Establish a socket connection and set nodelay settings on it.
83
:return: a new socket connection
104
:return: New socket connection.
86
107
if self.source_address: # Python 2.7+
87
108
extra_args.append(self.source_address)
89
conn = socket.create_connection(
90
(self.host, self.port), self.timeout, *extra_args)
92
socket.IPPROTO_TCP, socket.TCP_NODELAY, self.tcp_nodelay)
111
conn = socket.create_connection(
112
(self.host, self.port), self.timeout, *extra_args)
114
except SocketTimeout:
115
raise ConnectTimeoutError(
116
self, "Connection to %s timed out. (connect timeout=%s)" %
117
(self.host, self.timeout))
119
# Set options on the socket.
120
self._set_options_on(conn)
96
124
def _prepare_conn(self, conn):
126
# the _tunnel_host attribute was added in python 2.6.3 (via
127
# http://hg.python.org/cpython/rev/0f57b30a152f) so pythons 2.6(0-2) do
129
if getattr(self, '_tunnel_host', None):
99
130
# TODO: Fix tunnel so it doesn't depend on self.sock state.
132
# Mark this connection as not reusable
135
def _set_options_on(self, conn):
136
# Disable all socket options if the user passes ``socket_options=None``
137
if self.socket_options is None:
140
for opt in self.socket_options:
141
conn.setsockopt(*opt)
102
143
def connect(self):
103
144
conn = self._new_conn()
150
190
def connect(self):
151
191
# Add certificate verification
154
sock = socket.create_connection(
155
address=(self.host, self.port), timeout=self.timeout,
157
except SocketTimeout:
158
raise ConnectTimeoutError(
159
self, "Connection to %s timed out. (connect timeout=%s)" %
160
(self.host, self.timeout))
162
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY,
192
conn = self._new_conn()
165
194
resolved_cert_reqs = resolve_cert_reqs(self.cert_reqs)
166
195
resolved_ssl_version = resolve_ssl_version(self.ssl_version)
168
# the _tunnel_host attribute was added in python 2.6.3 (via
169
# http://hg.python.org/cpython/rev/0f57b30a152f) so pythons 2.6(0-2) do
171
198
if getattr(self, '_tunnel_host', None):
199
# _tunnel_host was added in Python 2.6.3
200
# (See: http://hg.python.org/cpython/rev/0f57b30a152f)
173
203
# Calls self._set_hostport(), so self.host is
174
204
# self._tunnel_host below.
206
# Mark this connection as not reusable
209
# Override the host with the one we're requesting data from.
210
hostname = self._tunnel_host
177
212
# Wrap socket using verification with the root certs in
178
213
# trusted_root_certs
179
self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file,
214
self.sock = ssl_wrap_socket(conn, self.key_file, self.cert_file,
180
215
cert_reqs=resolved_cert_reqs,
181
216
ca_certs=self.ca_certs,
182
server_hostname=self.host,
217
server_hostname=hostname,
183
218
ssl_version=resolved_ssl_version)
185
220
if resolved_cert_reqs != ssl.CERT_NONE: