OLD | NEW |
| (Empty) |
1 # urllib3/connectionpool.py | |
2 # Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) | |
3 # | |
4 # This module is part of urllib3 and is released under | |
5 # the MIT License: http://www.opensource.org/licenses/mit-license.php | |
6 | |
7 import errno | |
8 import logging | |
9 | |
10 from socket import error as SocketError, timeout as SocketTimeout | |
11 import socket | |
12 | |
13 try: # Python 3 | |
14 from http.client import HTTPConnection, HTTPException | |
15 from http.client import HTTP_PORT, HTTPS_PORT | |
16 except ImportError: | |
17 from httplib import HTTPConnection, HTTPException | |
18 from httplib import HTTP_PORT, HTTPS_PORT | |
19 | |
20 try: # Python 3 | |
21 from queue import LifoQueue, Empty, Full | |
22 except ImportError: | |
23 from Queue import LifoQueue, Empty, Full | |
24 import Queue as _ # Platform-specific: Windows | |
25 | |
26 | |
27 try: # Compiled with SSL? | |
28 HTTPSConnection = object | |
29 | |
30 class BaseSSLError(BaseException): | |
31 pass | |
32 | |
33 ssl = None | |
34 | |
35 try: # Python 3 | |
36 from http.client import HTTPSConnection | |
37 except ImportError: | |
38 from httplib import HTTPSConnection | |
39 | |
40 import ssl | |
41 BaseSSLError = ssl.SSLError | |
42 | |
43 except (ImportError, AttributeError): # Platform-specific: No SSL. | |
44 pass | |
45 | |
46 | |
47 from .exceptions import ( | |
48 ClosedPoolError, | |
49 ConnectTimeoutError, | |
50 EmptyPoolError, | |
51 HostChangedError, | |
52 MaxRetryError, | |
53 SSLError, | |
54 ReadTimeoutError, | |
55 ProxyError, | |
56 ) | |
57 from .packages.ssl_match_hostname import CertificateError, match_hostname | |
58 from .packages import six | |
59 from .request import RequestMethods | |
60 from .response import HTTPResponse | |
61 from .util import ( | |
62 assert_fingerprint, | |
63 get_host, | |
64 is_connection_dropped, | |
65 resolve_cert_reqs, | |
66 resolve_ssl_version, | |
67 ssl_wrap_socket, | |
68 Timeout, | |
69 ) | |
70 | |
71 xrange = six.moves.xrange | |
72 | |
73 log = logging.getLogger(__name__) | |
74 | |
75 _Default = object() | |
76 | |
77 port_by_scheme = { | |
78 'http': HTTP_PORT, | |
79 'https': HTTPS_PORT, | |
80 } | |
81 | |
82 | |
83 ## Connection objects (extension of httplib) | |
84 | |
85 class VerifiedHTTPSConnection(HTTPSConnection): | |
86 """ | |
87 Based on httplib.HTTPSConnection but wraps the socket with | |
88 SSL certification. | |
89 """ | |
90 cert_reqs = None | |
91 ca_certs = None | |
92 ssl_version = None | |
93 | |
94 def set_cert(self, key_file=None, cert_file=None, | |
95 cert_reqs=None, ca_certs=None, | |
96 assert_hostname=None, assert_fingerprint=None): | |
97 | |
98 self.key_file = key_file | |
99 self.cert_file = cert_file | |
100 self.cert_reqs = cert_reqs | |
101 self.ca_certs = ca_certs | |
102 self.assert_hostname = assert_hostname | |
103 self.assert_fingerprint = assert_fingerprint | |
104 | |
105 def connect(self): | |
106 # Add certificate verification | |
107 try: | |
108 sock = socket.create_connection( | |
109 address=(self.host, self.port), | |
110 timeout=self.timeout) | |
111 except SocketTimeout: | |
112 raise ConnectTimeoutError( | |
113 self, "Connection to %s timed out. (connect timeout=%s)" % | |
114 (self.host, self.timeout)) | |
115 | |
116 resolved_cert_reqs = resolve_cert_reqs(self.cert_reqs) | |
117 resolved_ssl_version = resolve_ssl_version(self.ssl_version) | |
118 | |
119 if self._tunnel_host: | |
120 self.sock = sock | |
121 # Calls self._set_hostport(), so self.host is | |
122 # self._tunnel_host below. | |
123 self._tunnel() | |
124 | |
125 # Wrap socket using verification with the root certs in | |
126 # trusted_root_certs | |
127 self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file, | |
128 cert_reqs=resolved_cert_reqs, | |
129 ca_certs=self.ca_certs, | |
130 server_hostname=self.host, | |
131 ssl_version=resolved_ssl_version) | |
132 | |
133 if resolved_cert_reqs != ssl.CERT_NONE: | |
134 if self.assert_fingerprint: | |
135 assert_fingerprint(self.sock.getpeercert(binary_form=True), | |
136 self.assert_fingerprint) | |
137 elif self.assert_hostname is not False: | |
138 match_hostname(self.sock.getpeercert(), | |
139 self.assert_hostname or self.host) | |
140 | |
141 | |
142 ## Pool objects | |
143 | |
144 class ConnectionPool(object): | |
145 """ | |
146 Base class for all connection pools, such as | |
147 :class:`.HTTPConnectionPool` and :class:`.HTTPSConnectionPool`. | |
148 """ | |
149 | |
150 scheme = None | |
151 QueueCls = LifoQueue | |
152 | |
153 def __init__(self, host, port=None): | |
154 # httplib doesn't like it when we include brackets in ipv6 addresses | |
155 host = host.strip('[]') | |
156 | |
157 self.host = host | |
158 self.port = port | |
159 | |
160 def __str__(self): | |
161 return '%s(host=%r, port=%r)' % (type(self).__name__, | |
162 self.host, self.port) | |
163 | |
164 # This is taken from http://hg.python.org/cpython/file/7aaba721ebc0/Lib/socket.p
y#l252 | |
165 _blocking_errnos = set([errno.EAGAIN, errno.EWOULDBLOCK]) | |
166 | |
167 class HTTPConnectionPool(ConnectionPool, RequestMethods): | |
168 """ | |
169 Thread-safe connection pool for one host. | |
170 | |
171 :param host: | |
172 Host used for this HTTP Connection (e.g. "localhost"), passed into | |
173 :class:`httplib.HTTPConnection`. | |
174 | |
175 :param port: | |
176 Port used for this HTTP Connection (None is equivalent to 80), passed | |
177 into :class:`httplib.HTTPConnection`. | |
178 | |
179 :param strict: | |
180 Causes BadStatusLine to be raised if the status line can't be parsed | |
181 as a valid HTTP/1.0 or 1.1 status line, passed into | |
182 :class:`httplib.HTTPConnection`. | |
183 | |
184 .. note:: | |
185 Only works in Python 2. This parameter is ignored in Python 3. | |
186 | |
187 :param timeout: | |
188 Socket timeout in seconds for each individual connection. This can | |
189 be a float or integer, which sets the timeout for the HTTP request, | |
190 or an instance of :class:`urllib3.util.Timeout` which gives you more | |
191 fine-grained control over request timeouts. After the constructor has | |
192 been parsed, this is always a `urllib3.util.Timeout` object. | |
193 | |
194 :param maxsize: | |
195 Number of connections to save that can be reused. More than 1 is useful | |
196 in multithreaded situations. If ``block`` is set to false, more | |
197 connections will be created but they will not be saved once they've | |
198 been used. | |
199 | |
200 :param block: | |
201 If set to True, no more than ``maxsize`` connections will be used at | |
202 a time. When no free connections are available, the call will block | |
203 until a connection has been released. This is a useful side effect for | |
204 particular multithreaded situations where one does not want to use more | |
205 than maxsize connections per host to prevent flooding. | |
206 | |
207 :param headers: | |
208 Headers to include with all requests, unless other headers are given | |
209 explicitly. | |
210 | |
211 :param _proxy: | |
212 Parsed proxy URL, should not be used directly, instead, see | |
213 :class:`urllib3.connectionpool.ProxyManager`" | |
214 | |
215 :param _proxy_headers: | |
216 A dictionary with proxy headers, should not be used directly, | |
217 instead, see :class:`urllib3.connectionpool.ProxyManager`" | |
218 """ | |
219 | |
220 scheme = 'http' | |
221 | |
222 def __init__(self, host, port=None, strict=False, | |
223 timeout=Timeout.DEFAULT_TIMEOUT, maxsize=1, block=False, | |
224 headers=None, _proxy=None, _proxy_headers=None): | |
225 ConnectionPool.__init__(self, host, port) | |
226 RequestMethods.__init__(self, headers) | |
227 | |
228 self.strict = strict | |
229 | |
230 # This is for backwards compatibility and can be removed once a timeout | |
231 # can only be set to a Timeout object | |
232 if not isinstance(timeout, Timeout): | |
233 timeout = Timeout.from_float(timeout) | |
234 | |
235 self.timeout = timeout | |
236 | |
237 self.pool = self.QueueCls(maxsize) | |
238 self.block = block | |
239 | |
240 self.proxy = _proxy | |
241 self.proxy_headers = _proxy_headers or {} | |
242 | |
243 # Fill the queue up so that doing get() on it will block properly | |
244 for _ in xrange(maxsize): | |
245 self.pool.put(None) | |
246 | |
247 # These are mostly for testing and debugging purposes. | |
248 self.num_connections = 0 | |
249 self.num_requests = 0 | |
250 | |
251 def _new_conn(self): | |
252 """ | |
253 Return a fresh :class:`httplib.HTTPConnection`. | |
254 """ | |
255 self.num_connections += 1 | |
256 log.info("Starting new HTTP connection (%d): %s" % | |
257 (self.num_connections, self.host)) | |
258 extra_params = {} | |
259 if not six.PY3: # Python 2 | |
260 extra_params['strict'] = self.strict | |
261 | |
262 return HTTPConnection(host=self.host, port=self.port, | |
263 timeout=self.timeout.connect_timeout, | |
264 **extra_params) | |
265 | |
266 | |
267 def _get_conn(self, timeout=None): | |
268 """ | |
269 Get a connection. Will return a pooled connection if one is available. | |
270 | |
271 If no connections are available and :prop:`.block` is ``False``, then a | |
272 fresh connection is returned. | |
273 | |
274 :param timeout: | |
275 Seconds to wait before giving up and raising | |
276 :class:`urllib3.exceptions.EmptyPoolError` if the pool is empty and | |
277 :prop:`.block` is ``True``. | |
278 """ | |
279 conn = None | |
280 try: | |
281 conn = self.pool.get(block=self.block, timeout=timeout) | |
282 | |
283 except AttributeError: # self.pool is None | |
284 raise ClosedPoolError(self, "Pool is closed.") | |
285 | |
286 except Empty: | |
287 if self.block: | |
288 raise EmptyPoolError(self, | |
289 "Pool reached maximum size and no more " | |
290 "connections are allowed.") | |
291 pass # Oh well, we'll create a new connection then | |
292 | |
293 # If this is a persistent connection, check if it got disconnected | |
294 if conn and is_connection_dropped(conn): | |
295 log.info("Resetting dropped connection: %s" % self.host) | |
296 conn.close() | |
297 | |
298 return conn or self._new_conn() | |
299 | |
300 def _put_conn(self, conn): | |
301 """ | |
302 Put a connection back into the pool. | |
303 | |
304 :param conn: | |
305 Connection object for the current host and port as returned by | |
306 :meth:`._new_conn` or :meth:`._get_conn`. | |
307 | |
308 If the pool is already full, the connection is closed and discarded | |
309 because we exceeded maxsize. If connections are discarded frequently, | |
310 then maxsize should be increased. | |
311 | |
312 If the pool is closed, then the connection will be closed and discarded. | |
313 """ | |
314 try: | |
315 self.pool.put(conn, block=False) | |
316 return # Everything is dandy, done. | |
317 except AttributeError: | |
318 # self.pool is None. | |
319 pass | |
320 except Full: | |
321 # This should never happen if self.block == True | |
322 log.warning("HttpConnectionPool is full, discarding connection: %s" | |
323 % self.host) | |
324 | |
325 # Connection never got put back into the pool, close it. | |
326 if conn: | |
327 conn.close() | |
328 | |
329 def _get_timeout(self, timeout): | |
330 """ Helper that always returns a :class:`urllib3.util.Timeout` """ | |
331 if timeout is _Default: | |
332 return self.timeout.clone() | |
333 | |
334 if isinstance(timeout, Timeout): | |
335 return timeout.clone() | |
336 else: | |
337 # User passed us an int/float. This is for backwards compatibility, | |
338 # can be removed later | |
339 return Timeout.from_float(timeout) | |
340 | |
341 def _make_request(self, conn, method, url, timeout=_Default, | |
342 **httplib_request_kw): | |
343 """ | |
344 Perform a request on a given httplib connection object taken from our | |
345 pool. | |
346 | |
347 :param conn: | |
348 a connection from one of our connection pools | |
349 | |
350 :param timeout: | |
351 Socket timeout in seconds for the request. This can be a | |
352 float or integer, which will set the same timeout value for | |
353 the socket connect and the socket read, or an instance of | |
354 :class:`urllib3.util.Timeout`, which gives you more fine-grained | |
355 control over your timeouts. | |
356 """ | |
357 self.num_requests += 1 | |
358 | |
359 timeout_obj = self._get_timeout(timeout) | |
360 | |
361 try: | |
362 timeout_obj.start_connect() | |
363 conn.timeout = timeout_obj.connect_timeout | |
364 # conn.request() calls httplib.*.request, not the method in | |
365 # request.py. It also calls makefile (recv) on the socket | |
366 conn.request(method, url, **httplib_request_kw) | |
367 except SocketTimeout: | |
368 raise ConnectTimeoutError( | |
369 self, "Connection to %s timed out. (connect timeout=%s)" % | |
370 (self.host, timeout_obj.connect_timeout)) | |
371 | |
372 # Reset the timeout for the recv() on the socket | |
373 read_timeout = timeout_obj.read_timeout | |
374 log.debug("Setting read timeout to %s" % read_timeout) | |
375 # App Engine doesn't have a sock attr | |
376 if hasattr(conn, 'sock') and \ | |
377 read_timeout is not None and \ | |
378 read_timeout is not Timeout.DEFAULT_TIMEOUT: | |
379 # In Python 3 socket.py will catch EAGAIN and return None when you | |
380 # try and read into the file pointer created by http.client, which | |
381 # instead raises a BadStatusLine exception. Instead of catching | |
382 # the exception and assuming all BadStatusLine exceptions are read | |
383 # timeouts, check for a zero timeout before making the request. | |
384 if read_timeout == 0: | |
385 raise ReadTimeoutError( | |
386 self, url, | |
387 "Read timed out. (read timeout=%s)" % read_timeout) | |
388 conn.sock.settimeout(read_timeout) | |
389 | |
390 # Receive the response from the server | |
391 try: | |
392 try: # Python 2.7+, use buffering of HTTP responses | |
393 httplib_response = conn.getresponse(buffering=True) | |
394 except TypeError: # Python 2.6 and older | |
395 httplib_response = conn.getresponse() | |
396 except SocketTimeout: | |
397 raise ReadTimeoutError( | |
398 self, url, "Read timed out. (read timeout=%s)" % read_timeout) | |
399 | |
400 except SocketError as e: # Platform-specific: Python 2 | |
401 # See the above comment about EAGAIN in Python 3. In Python 2 we | |
402 # have to specifically catch it and throw the timeout error | |
403 if e.errno in _blocking_errnos: | |
404 raise ReadTimeoutError( | |
405 self, url, | |
406 "Read timed out. (read timeout=%s)" % read_timeout) | |
407 raise | |
408 | |
409 | |
410 # AppEngine doesn't have a version attr. | |
411 http_version = getattr(conn, '_http_vsn_str', 'HTTP/?') | |
412 log.debug("\"%s %s %s\" %s %s" % (method, url, http_version, | |
413 httplib_response.status, | |
414 httplib_response.length)) | |
415 return httplib_response | |
416 | |
417 def close(self): | |
418 """ | |
419 Close all pooled connections and disable the pool. | |
420 """ | |
421 # Disable access to the pool | |
422 old_pool, self.pool = self.pool, None | |
423 | |
424 try: | |
425 while True: | |
426 conn = old_pool.get(block=False) | |
427 if conn: | |
428 conn.close() | |
429 | |
430 except Empty: | |
431 pass # Done. | |
432 | |
433 def is_same_host(self, url): | |
434 """ | |
435 Check if the given ``url`` is a member of the same host as this | |
436 connection pool. | |
437 """ | |
438 if url.startswith('/'): | |
439 return True | |
440 | |
441 # TODO: Add optional support for socket.gethostbyname checking. | |
442 scheme, host, port = get_host(url) | |
443 | |
444 if self.port and not port: | |
445 # Use explicit default port for comparison when none is given. | |
446 port = port_by_scheme.get(scheme) | |
447 | |
448 return (scheme, host, port) == (self.scheme, self.host, self.port) | |
449 | |
450 def urlopen(self, method, url, body=None, headers=None, retries=3, | |
451 redirect=True, assert_same_host=True, timeout=_Default, | |
452 pool_timeout=None, release_conn=None, **response_kw): | |
453 """ | |
454 Get a connection from the pool and perform an HTTP request. This is the | |
455 lowest level call for making a request, so you'll need to specify all | |
456 the raw details. | |
457 | |
458 .. note:: | |
459 | |
460 More commonly, it's appropriate to use a convenience method provided | |
461 by :class:`.RequestMethods`, such as :meth:`request`. | |
462 | |
463 .. note:: | |
464 | |
465 `release_conn` will only behave as expected if | |
466 `preload_content=False` because we want to make | |
467 `preload_content=False` the default behaviour someday soon without | |
468 breaking backwards compatibility. | |
469 | |
470 :param method: | |
471 HTTP request method (such as GET, POST, PUT, etc.) | |
472 | |
473 :param body: | |
474 Data to send in the request body (useful for creating | |
475 POST requests, see HTTPConnectionPool.post_url for | |
476 more convenience). | |
477 | |
478 :param headers: | |
479 Dictionary of custom headers to send, such as User-Agent, | |
480 If-None-Match, etc. If None, pool headers are used. If provided, | |
481 these headers completely replace any pool-specific headers. | |
482 | |
483 :param retries: | |
484 Number of retries to allow before raising a MaxRetryError exception. | |
485 | |
486 :param redirect: | |
487 If True, automatically handle redirects (status codes 301, 302, | |
488 303, 307, 308). Each redirect counts as a retry. | |
489 | |
490 :param assert_same_host: | |
491 If ``True``, will make sure that the host of the pool requests is | |
492 consistent else will raise HostChangedError. When False, you can | |
493 use the pool on an HTTP proxy and request foreign hosts. | |
494 | |
495 :param timeout: | |
496 If specified, overrides the default timeout for this one | |
497 request. It may be a float (in seconds) or an instance of | |
498 :class:`urllib3.util.Timeout`. | |
499 | |
500 :param pool_timeout: | |
501 If set and the pool is set to block=True, then this method will | |
502 block for ``pool_timeout`` seconds and raise EmptyPoolError if no | |
503 connection is available within the time period. | |
504 | |
505 :param release_conn: | |
506 If False, then the urlopen call will not release the connection | |
507 back into the pool once a response is received (but will release if | |
508 you read the entire contents of the response such as when | |
509 `preload_content=True`). This is useful if you're not preloading | |
510 the response's content immediately. You will need to call | |
511 ``r.release_conn()`` on the response ``r`` to return the connection | |
512 back into the pool. If None, it takes the value of | |
513 ``response_kw.get('preload_content', True)``. | |
514 | |
515 :param \**response_kw: | |
516 Additional parameters are passed to | |
517 :meth:`urllib3.response.HTTPResponse.from_httplib` | |
518 """ | |
519 if headers is None: | |
520 headers = self.headers | |
521 | |
522 if retries < 0: | |
523 raise MaxRetryError(self, url) | |
524 | |
525 if release_conn is None: | |
526 release_conn = response_kw.get('preload_content', True) | |
527 | |
528 # Check host | |
529 if assert_same_host and not self.is_same_host(url): | |
530 raise HostChangedError(self, url, retries - 1) | |
531 | |
532 conn = None | |
533 | |
534 try: | |
535 # Request a connection from the queue | |
536 conn = self._get_conn(timeout=pool_timeout) | |
537 | |
538 # Make the request on the httplib connection object | |
539 httplib_response = self._make_request(conn, method, url, | |
540 timeout=timeout, | |
541 body=body, headers=headers) | |
542 | |
543 # If we're going to release the connection in ``finally:``, then | |
544 # the request doesn't need to know about the connection. Otherwise | |
545 # it will also try to release it and we'll have a double-release | |
546 # mess. | |
547 response_conn = not release_conn and conn | |
548 | |
549 # Import httplib's response into our own wrapper object | |
550 response = HTTPResponse.from_httplib(httplib_response, | |
551 pool=self, | |
552 connection=response_conn, | |
553 **response_kw) | |
554 | |
555 # else: | |
556 # The connection will be put back into the pool when | |
557 # ``response.release_conn()`` is called (implicitly by | |
558 # ``response.read()``) | |
559 | |
560 except Empty: | |
561 # Timed out by queue | |
562 raise ReadTimeoutError( | |
563 self, url, "Read timed out, no pool connections are available.") | |
564 | |
565 except SocketTimeout: | |
566 # Timed out by socket | |
567 raise ReadTimeoutError(self, url, "Read timed out.") | |
568 | |
569 except BaseSSLError as e: | |
570 # SSL certificate error | |
571 if 'timed out' in str(e) or \ | |
572 'did not complete (read)' in str(e): # Platform-specific: Python
2.6 | |
573 raise ReadTimeoutError(self, url, "Read timed out.") | |
574 raise SSLError(e) | |
575 | |
576 except CertificateError as e: | |
577 # Name mismatch | |
578 raise SSLError(e) | |
579 | |
580 except (HTTPException, SocketError) as e: | |
581 if isinstance(e, SocketError) and self.proxy is not None: | |
582 raise ProxyError('Cannot connect to proxy. ' | |
583 'Socket error: %s.' % e) | |
584 | |
585 # Connection broken, discard. It will be replaced next _get_conn(). | |
586 conn = None | |
587 # This is necessary so we can access e below | |
588 err = e | |
589 | |
590 if retries == 0: | |
591 raise MaxRetryError(self, url, e) | |
592 | |
593 finally: | |
594 if release_conn: | |
595 # Put the connection back to be reused. If the connection is | |
596 # expired then it will be None, which will get replaced with a | |
597 # fresh connection during _get_conn. | |
598 self._put_conn(conn) | |
599 | |
600 if not conn: | |
601 # Try again | |
602 log.warn("Retrying (%d attempts remain) after connection " | |
603 "broken by '%r': %s" % (retries, err, url)) | |
604 return self.urlopen(method, url, body, headers, retries - 1, | |
605 redirect, assert_same_host, | |
606 timeout=timeout, pool_timeout=pool_timeout, | |
607 release_conn=release_conn, **response_kw) | |
608 | |
609 # Handle redirect? | |
610 redirect_location = redirect and response.get_redirect_location() | |
611 if redirect_location: | |
612 if response.status == 303: | |
613 method = 'GET' | |
614 log.info("Redirecting %s -> %s" % (url, redirect_location)) | |
615 return self.urlopen(method, redirect_location, body, headers, | |
616 retries - 1, redirect, assert_same_host, | |
617 timeout=timeout, pool_timeout=pool_timeout, | |
618 release_conn=release_conn, **response_kw) | |
619 | |
620 return response | |
621 | |
622 | |
623 class HTTPSConnectionPool(HTTPConnectionPool): | |
624 """ | |
625 Same as :class:`.HTTPConnectionPool`, but HTTPS. | |
626 | |
627 When Python is compiled with the :mod:`ssl` module, then | |
628 :class:`.VerifiedHTTPSConnection` is used, which *can* verify certificates, | |
629 instead of :class:`httplib.HTTPSConnection`. | |
630 | |
631 :class:`.VerifiedHTTPSConnection` uses one of ``assert_fingerprint``, | |
632 ``assert_hostname`` and ``host`` in this order to verify connections. | |
633 If ``assert_hostname`` is False, no verification is done. | |
634 | |
635 The ``key_file``, ``cert_file``, ``cert_reqs``, ``ca_certs`` and | |
636 ``ssl_version`` are only used if :mod:`ssl` is available and are fed into | |
637 :meth:`urllib3.util.ssl_wrap_socket` to upgrade the connection socket | |
638 into an SSL socket. | |
639 """ | |
640 | |
641 scheme = 'https' | |
642 | |
643 def __init__(self, host, port=None, | |
644 strict=False, timeout=None, maxsize=1, | |
645 block=False, headers=None, | |
646 _proxy=None, _proxy_headers=None, | |
647 key_file=None, cert_file=None, cert_reqs=None, | |
648 ca_certs=None, ssl_version=None, | |
649 assert_hostname=None, assert_fingerprint=None): | |
650 | |
651 HTTPConnectionPool.__init__(self, host, port, strict, timeout, maxsize, | |
652 block, headers, _proxy, _proxy_headers) | |
653 self.key_file = key_file | |
654 self.cert_file = cert_file | |
655 self.cert_reqs = cert_reqs | |
656 self.ca_certs = ca_certs | |
657 self.ssl_version = ssl_version | |
658 self.assert_hostname = assert_hostname | |
659 self.assert_fingerprint = assert_fingerprint | |
660 | |
661 def _prepare_conn(self, connection): | |
662 """ | |
663 Prepare the ``connection`` for :meth:`urllib3.util.ssl_wrap_socket` | |
664 and establish the tunnel if proxy is used. | |
665 """ | |
666 | |
667 if isinstance(connection, VerifiedHTTPSConnection): | |
668 connection.set_cert(key_file=self.key_file, | |
669 cert_file=self.cert_file, | |
670 cert_reqs=self.cert_reqs, | |
671 ca_certs=self.ca_certs, | |
672 assert_hostname=self.assert_hostname, | |
673 assert_fingerprint=self.assert_fingerprint) | |
674 connection.ssl_version = self.ssl_version | |
675 | |
676 if self.proxy is not None: | |
677 # Python 2.7+ | |
678 try: | |
679 set_tunnel = connection.set_tunnel | |
680 except AttributeError: # Platform-specific: Python 2.6 | |
681 set_tunnel = connection._set_tunnel | |
682 set_tunnel(self.host, self.port, self.proxy_headers) | |
683 # Establish tunnel connection early, because otherwise httplib | |
684 # would improperly set Host: header to proxy's IP:port. | |
685 connection.connect() | |
686 | |
687 return connection | |
688 | |
689 def _new_conn(self): | |
690 """ | |
691 Return a fresh :class:`httplib.HTTPSConnection`. | |
692 """ | |
693 self.num_connections += 1 | |
694 log.info("Starting new HTTPS connection (%d): %s" | |
695 % (self.num_connections, self.host)) | |
696 | |
697 actual_host = self.host | |
698 actual_port = self.port | |
699 if self.proxy is not None: | |
700 actual_host = self.proxy.host | |
701 actual_port = self.proxy.port | |
702 | |
703 if not ssl: # Platform-specific: Python compiled without +ssl | |
704 if not HTTPSConnection or HTTPSConnection is object: | |
705 raise SSLError("Can't connect to HTTPS URL because the SSL " | |
706 "module is not available.") | |
707 connection_class = HTTPSConnection | |
708 else: | |
709 connection_class = VerifiedHTTPSConnection | |
710 | |
711 extra_params = {} | |
712 if not six.PY3: # Python 2 | |
713 extra_params['strict'] = self.strict | |
714 connection = connection_class(host=actual_host, port=actual_port, | |
715 timeout=self.timeout.connect_timeout, | |
716 **extra_params) | |
717 | |
718 return self._prepare_conn(connection) | |
719 | |
720 | |
721 def connection_from_url(url, **kw): | |
722 """ | |
723 Given a url, return an :class:`.ConnectionPool` instance of its host. | |
724 | |
725 This is a shortcut for not having to parse out the scheme, host, and port | |
726 of the url before creating an :class:`.ConnectionPool` instance. | |
727 | |
728 :param url: | |
729 Absolute URL string that must include the scheme. Port is optional. | |
730 | |
731 :param \**kw: | |
732 Passes additional parameters to the constructor of the appropriate | |
733 :class:`.ConnectionPool`. Useful for specifying things like | |
734 timeout, maxsize, headers, etc. | |
735 | |
736 Example: :: | |
737 | |
738 >>> conn = connection_from_url('http://google.com/') | |
739 >>> r = conn.request('GET', '/') | |
740 """ | |
741 scheme, host, port = get_host(url) | |
742 if scheme == 'https': | |
743 return HTTPSConnectionPool(host, port=port, **kw) | |
744 else: | |
745 return HTTPConnectionPool(host, port=port, **kw) | |
OLD | NEW |