Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: third_party/google-endpoints/urllib3/connectionpool.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 from __future__ import absolute_import
2 import errno
3 import logging
4 import sys
5 import warnings
6
7 from socket import error as SocketError, timeout as SocketTimeout
8 import socket
9
10
11 from .exceptions import (
12 ClosedPoolError,
13 ProtocolError,
14 EmptyPoolError,
15 HeaderParsingError,
16 HostChangedError,
17 LocationValueError,
18 MaxRetryError,
19 ProxyError,
20 ReadTimeoutError,
21 SSLError,
22 TimeoutError,
23 InsecureRequestWarning,
24 NewConnectionError,
25 )
26 from .packages.ssl_match_hostname import CertificateError
27 from .packages import six
28 from .packages.six.moves import queue
29 from .connection import (
30 port_by_scheme,
31 DummyConnection,
32 HTTPConnection, HTTPSConnection, VerifiedHTTPSConnection,
33 HTTPException, BaseSSLError,
34 )
35 from .request import RequestMethods
36 from .response import HTTPResponse
37
38 from .util.connection import is_connection_dropped
39 from .util.request import set_file_position
40 from .util.response import assert_header_parsing
41 from .util.retry import Retry
42 from .util.timeout import Timeout
43 from .util.url import get_host, Url
44
45
46 if six.PY2:
47 # Queue is imported for side effects on MS Windows
48 import Queue as _unused_module_Queue # noqa: F401
49
50 xrange = six.moves.xrange
51
52 log = logging.getLogger(__name__)
53
54 _Default = object()
55
56
57 # Pool objects
58 class ConnectionPool(object):
59 """
60 Base class for all connection pools, such as
61 :class:`.HTTPConnectionPool` and :class:`.HTTPSConnectionPool`.
62 """
63
64 scheme = None
65 QueueCls = queue.LifoQueue
66
67 def __init__(self, host, port=None):
68 if not host:
69 raise LocationValueError("No host specified.")
70
71 self.host = _ipv6_host(host).lower()
72 self.port = port
73
74 def __str__(self):
75 return '%s(host=%r, port=%r)' % (type(self).__name__,
76 self.host, self.port)
77
78 def __enter__(self):
79 return self
80
81 def __exit__(self, exc_type, exc_val, exc_tb):
82 self.close()
83 # Return False to re-raise any potential exceptions
84 return False
85
86 def close(self):
87 """
88 Close all pooled connections and disable the pool.
89 """
90 pass
91
92
93 # This is taken from http://hg.python.org/cpython/file/7aaba721ebc0/Lib/socket.p y#l252
94 _blocking_errnos = set([errno.EAGAIN, errno.EWOULDBLOCK])
95
96
97 class HTTPConnectionPool(ConnectionPool, RequestMethods):
98 """
99 Thread-safe connection pool for one host.
100
101 :param host:
102 Host used for this HTTP Connection (e.g. "localhost"), passed into
103 :class:`httplib.HTTPConnection`.
104
105 :param port:
106 Port used for this HTTP Connection (None is equivalent to 80), passed
107 into :class:`httplib.HTTPConnection`.
108
109 :param strict:
110 Causes BadStatusLine to be raised if the status line can't be parsed
111 as a valid HTTP/1.0 or 1.1 status line, passed into
112 :class:`httplib.HTTPConnection`.
113
114 .. note::
115 Only works in Python 2. This parameter is ignored in Python 3.
116
117 :param timeout:
118 Socket timeout in seconds for each individual connection. This can
119 be a float or integer, which sets the timeout for the HTTP request,
120 or an instance of :class:`urllib3.util.Timeout` which gives you more
121 fine-grained control over request timeouts. After the constructor has
122 been parsed, this is always a `urllib3.util.Timeout` object.
123
124 :param maxsize:
125 Number of connections to save that can be reused. More than 1 is useful
126 in multithreaded situations. If ``block`` is set to False, more
127 connections will be created but they will not be saved once they've
128 been used.
129
130 :param block:
131 If set to True, no more than ``maxsize`` connections will be used at
132 a time. When no free connections are available, the call will block
133 until a connection has been released. This is a useful side effect for
134 particular multithreaded situations where one does not want to use more
135 than maxsize connections per host to prevent flooding.
136
137 :param headers:
138 Headers to include with all requests, unless other headers are given
139 explicitly.
140
141 :param retries:
142 Retry configuration to use by default with requests in this pool.
143
144 :param _proxy:
145 Parsed proxy URL, should not be used directly, instead, see
146 :class:`urllib3.connectionpool.ProxyManager`"
147
148 :param _proxy_headers:
149 A dictionary with proxy headers, should not be used directly,
150 instead, see :class:`urllib3.connectionpool.ProxyManager`"
151
152 :param \\**conn_kw:
153 Additional parameters are used to create fresh :class:`urllib3.connectio n.HTTPConnection`,
154 :class:`urllib3.connection.HTTPSConnection` instances.
155 """
156
157 scheme = 'http'
158 ConnectionCls = HTTPConnection
159 ResponseCls = HTTPResponse
160
161 def __init__(self, host, port=None, strict=False,
162 timeout=Timeout.DEFAULT_TIMEOUT, maxsize=1, block=False,
163 headers=None, retries=None,
164 _proxy=None, _proxy_headers=None,
165 **conn_kw):
166 ConnectionPool.__init__(self, host, port)
167 RequestMethods.__init__(self, headers)
168
169 self.strict = strict
170
171 if not isinstance(timeout, Timeout):
172 timeout = Timeout.from_float(timeout)
173
174 if retries is None:
175 retries = Retry.DEFAULT
176
177 self.timeout = timeout
178 self.retries = retries
179
180 self.pool = self.QueueCls(maxsize)
181 self.block = block
182
183 self.proxy = _proxy
184 self.proxy_headers = _proxy_headers or {}
185
186 # Fill the queue up so that doing get() on it will block properly
187 for _ in xrange(maxsize):
188 self.pool.put(None)
189
190 # These are mostly for testing and debugging purposes.
191 self.num_connections = 0
192 self.num_requests = 0
193 self.conn_kw = conn_kw
194
195 if self.proxy:
196 # Enable Nagle's algorithm for proxies, to avoid packet fragmentatio n.
197 # We cannot know if the user has added default socket options, so we cannot replace the
198 # list.
199 self.conn_kw.setdefault('socket_options', [])
200
201 def _new_conn(self):
202 """
203 Return a fresh :class:`HTTPConnection`.
204 """
205 self.num_connections += 1
206 log.debug("Starting new HTTP connection (%d): %s",
207 self.num_connections, self.host)
208
209 conn = self.ConnectionCls(host=self.host, port=self.port,
210 timeout=self.timeout.connect_timeout,
211 strict=self.strict, **self.conn_kw)
212 return conn
213
214 def _get_conn(self, timeout=None):
215 """
216 Get a connection. Will return a pooled connection if one is available.
217
218 If no connections are available and :prop:`.block` is ``False``, then a
219 fresh connection is returned.
220
221 :param timeout:
222 Seconds to wait before giving up and raising
223 :class:`urllib3.exceptions.EmptyPoolError` if the pool is empty and
224 :prop:`.block` is ``True``.
225 """
226 conn = None
227 try:
228 conn = self.pool.get(block=self.block, timeout=timeout)
229
230 except AttributeError: # self.pool is None
231 raise ClosedPoolError(self, "Pool is closed.")
232
233 except queue.Empty:
234 if self.block:
235 raise EmptyPoolError(self,
236 "Pool reached maximum size and no more "
237 "connections are allowed.")
238 pass # Oh well, we'll create a new connection then
239
240 # If this is a persistent connection, check if it got disconnected
241 if conn and is_connection_dropped(conn):
242 log.debug("Resetting dropped connection: %s", self.host)
243 conn.close()
244 if getattr(conn, 'auto_open', 1) == 0:
245 # This is a proxied connection that has been mutated by
246 # httplib._tunnel() and cannot be reused (since it would
247 # attempt to bypass the proxy)
248 conn = None
249
250 return conn or self._new_conn()
251
252 def _put_conn(self, conn):
253 """
254 Put a connection back into the pool.
255
256 :param conn:
257 Connection object for the current host and port as returned by
258 :meth:`._new_conn` or :meth:`._get_conn`.
259
260 If the pool is already full, the connection is closed and discarded
261 because we exceeded maxsize. If connections are discarded frequently,
262 then maxsize should be increased.
263
264 If the pool is closed, then the connection will be closed and discarded.
265 """
266 try:
267 self.pool.put(conn, block=False)
268 return # Everything is dandy, done.
269 except AttributeError:
270 # self.pool is None.
271 pass
272 except queue.Full:
273 # This should never happen if self.block == True
274 log.warning(
275 "Connection pool is full, discarding connection: %s",
276 self.host)
277
278 # Connection never got put back into the pool, close it.
279 if conn:
280 conn.close()
281
282 def _validate_conn(self, conn):
283 """
284 Called right before a request is made, after the socket is created.
285 """
286 pass
287
288 def _prepare_proxy(self, conn):
289 # Nothing to do for HTTP connections.
290 pass
291
292 def _get_timeout(self, timeout):
293 """ Helper that always returns a :class:`urllib3.util.Timeout` """
294 if timeout is _Default:
295 return self.timeout.clone()
296
297 if isinstance(timeout, Timeout):
298 return timeout.clone()
299 else:
300 # User passed us an int/float. This is for backwards compatibility,
301 # can be removed later
302 return Timeout.from_float(timeout)
303
304 def _raise_timeout(self, err, url, timeout_value):
305 """Is the error actually a timeout? Will raise a ReadTimeout or pass"""
306
307 if isinstance(err, SocketTimeout):
308 raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s) " % timeout_value)
309
310 # See the above comment about EAGAIN in Python 3. In Python 2 we have
311 # to specifically catch it and throw the timeout error
312 if hasattr(err, 'errno') and err.errno in _blocking_errnos:
313 raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s) " % timeout_value)
314
315 # Catch possible read timeouts thrown as SSL errors. If not the
316 # case, rethrow the original. We need to do this because of:
317 # http://bugs.python.org/issue10272
318 if 'timed out' in str(err) or 'did not complete (read)' in str(err): # Python 2.6
319 raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s) " % timeout_value)
320
321 def _make_request(self, conn, method, url, timeout=_Default, chunked=False,
322 **httplib_request_kw):
323 """
324 Perform a request on a given urllib connection object taken from our
325 pool.
326
327 :param conn:
328 a connection from one of our connection pools
329
330 :param timeout:
331 Socket timeout in seconds for the request. This can be a
332 float or integer, which will set the same timeout value for
333 the socket connect and the socket read, or an instance of
334 :class:`urllib3.util.Timeout`, which gives you more fine-grained
335 control over your timeouts.
336 """
337 self.num_requests += 1
338
339 timeout_obj = self._get_timeout(timeout)
340 timeout_obj.start_connect()
341 conn.timeout = timeout_obj.connect_timeout
342
343 # Trigger any extra validation we need to do.
344 try:
345 self._validate_conn(conn)
346 except (SocketTimeout, BaseSSLError) as e:
347 # Py2 raises this as a BaseSSLError, Py3 raises it as socket timeout .
348 self._raise_timeout(err=e, url=url, timeout_value=conn.timeout)
349 raise
350
351 # conn.request() calls httplib.*.request, not the method in
352 # urllib3.request. It also calls makefile (recv) on the socket.
353 if chunked:
354 conn.request_chunked(method, url, **httplib_request_kw)
355 else:
356 conn.request(method, url, **httplib_request_kw)
357
358 # Reset the timeout for the recv() on the socket
359 read_timeout = timeout_obj.read_timeout
360
361 # App Engine doesn't have a sock attr
362 if getattr(conn, 'sock', None):
363 # In Python 3 socket.py will catch EAGAIN and return None when you
364 # try and read into the file pointer created by http.client, which
365 # instead raises a BadStatusLine exception. Instead of catching
366 # the exception and assuming all BadStatusLine exceptions are read
367 # timeouts, check for a zero timeout before making the request.
368 if read_timeout == 0:
369 raise ReadTimeoutError(
370 self, url, "Read timed out. (read timeout=%s)" % read_timeou t)
371 if read_timeout is Timeout.DEFAULT_TIMEOUT:
372 conn.sock.settimeout(socket.getdefaulttimeout())
373 else: # None or a value
374 conn.sock.settimeout(read_timeout)
375
376 # Receive the response from the server
377 try:
378 try: # Python 2.7, use buffering of HTTP responses
379 httplib_response = conn.getresponse(buffering=True)
380 except TypeError: # Python 2.6 and older, Python 3
381 try:
382 httplib_response = conn.getresponse()
383 except Exception as e:
384 # Remove the TypeError from the exception chain in Python 3;
385 # otherwise it looks like a programming error was the cause.
386 six.raise_from(e, None)
387 except (SocketTimeout, BaseSSLError, SocketError) as e:
388 self._raise_timeout(err=e, url=url, timeout_value=read_timeout)
389 raise
390
391 # AppEngine doesn't have a version attr.
392 http_version = getattr(conn, '_http_vsn_str', 'HTTP/?')
393 log.debug("%s://%s:%s \"%s %s %s\" %s %s", self.scheme, self.host, self. port,
394 method, url, http_version, httplib_response.status,
395 httplib_response.length)
396
397 try:
398 assert_header_parsing(httplib_response.msg)
399 except HeaderParsingError as hpe: # Platform-specific: Python 3
400 log.warning(
401 'Failed to parse headers (url=%s): %s',
402 self._absolute_url(url), hpe, exc_info=True)
403
404 return httplib_response
405
406 def _absolute_url(self, path):
407 return Url(scheme=self.scheme, host=self.host, port=self.port, path=path ).url
408
409 def close(self):
410 """
411 Close all pooled connections and disable the pool.
412 """
413 # Disable access to the pool
414 old_pool, self.pool = self.pool, None
415
416 try:
417 while True:
418 conn = old_pool.get(block=False)
419 if conn:
420 conn.close()
421
422 except queue.Empty:
423 pass # Done.
424
425 def is_same_host(self, url):
426 """
427 Check if the given ``url`` is a member of the same host as this
428 connection pool.
429 """
430 if url.startswith('/'):
431 return True
432
433 # TODO: Add optional support for socket.gethostbyname checking.
434 scheme, host, port = get_host(url)
435
436 host = _ipv6_host(host).lower()
437
438 # Use explicit default port for comparison when none is given
439 if self.port and not port:
440 port = port_by_scheme.get(scheme)
441 elif not self.port and port == port_by_scheme.get(scheme):
442 port = None
443
444 return (scheme, host, port) == (self.scheme, self.host, self.port)
445
446 def urlopen(self, method, url, body=None, headers=None, retries=None,
447 redirect=True, assert_same_host=True, timeout=_Default,
448 pool_timeout=None, release_conn=None, chunked=False,
449 body_pos=None, **response_kw):
450 """
451 Get a connection from the pool and perform an HTTP request. This is the
452 lowest level call for making a request, so you'll need to specify all
453 the raw details.
454
455 .. note::
456
457 More commonly, it's appropriate to use a convenience method provided
458 by :class:`.RequestMethods`, such as :meth:`request`.
459
460 .. note::
461
462 `release_conn` will only behave as expected if
463 `preload_content=False` because we want to make
464 `preload_content=False` the default behaviour someday soon without
465 breaking backwards compatibility.
466
467 :param method:
468 HTTP request method (such as GET, POST, PUT, etc.)
469
470 :param body:
471 Data to send in the request body (useful for creating
472 POST requests, see HTTPConnectionPool.post_url for
473 more convenience).
474
475 :param headers:
476 Dictionary of custom headers to send, such as User-Agent,
477 If-None-Match, etc. If None, pool headers are used. If provided,
478 these headers completely replace any pool-specific headers.
479
480 :param retries:
481 Configure the number of retries to allow before raising a
482 :class:`~urllib3.exceptions.MaxRetryError` exception.
483
484 Pass ``None`` to retry until you receive a response. Pass a
485 :class:`~urllib3.util.retry.Retry` object for fine-grained control
486 over different types of retries.
487 Pass an integer number to retry connection errors that many times,
488 but no other types of errors. Pass zero to never retry.
489
490 If ``False``, then retries are disabled and any exception is raised
491 immediately. Also, instead of raising a MaxRetryError on redirects,
492 the redirect response will be returned.
493
494 :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
495
496 :param redirect:
497 If True, automatically handle redirects (status codes 301, 302,
498 303, 307, 308). Each redirect counts as a retry. Disabling retries
499 will disable redirect, too.
500
501 :param assert_same_host:
502 If ``True``, will make sure that the host of the pool requests is
503 consistent else will raise HostChangedError. When False, you can
504 use the pool on an HTTP proxy and request foreign hosts.
505
506 :param timeout:
507 If specified, overrides the default timeout for this one
508 request. It may be a float (in seconds) or an instance of
509 :class:`urllib3.util.Timeout`.
510
511 :param pool_timeout:
512 If set and the pool is set to block=True, then this method will
513 block for ``pool_timeout`` seconds and raise EmptyPoolError if no
514 connection is available within the time period.
515
516 :param release_conn:
517 If False, then the urlopen call will not release the connection
518 back into the pool once a response is received (but will release if
519 you read the entire contents of the response such as when
520 `preload_content=True`). This is useful if you're not preloading
521 the response's content immediately. You will need to call
522 ``r.release_conn()`` on the response ``r`` to return the connection
523 back into the pool. If None, it takes the value of
524 ``response_kw.get('preload_content', True)``.
525
526 :param chunked:
527 If True, urllib3 will send the body using chunked transfer
528 encoding. Otherwise, urllib3 will send the body using the standard
529 content-length form. Defaults to False.
530
531 :param int body_pos:
532 Position to seek to in file-like body in the event of a retry or
533 redirect. Typically this won't need to be set because urllib3 will
534 auto-populate the value when needed.
535
536 :param \\**response_kw:
537 Additional parameters are passed to
538 :meth:`urllib3.response.HTTPResponse.from_httplib`
539 """
540 if headers is None:
541 headers = self.headers
542
543 if not isinstance(retries, Retry):
544 retries = Retry.from_int(retries, redirect=redirect, default=self.re tries)
545
546 if release_conn is None:
547 release_conn = response_kw.get('preload_content', True)
548
549 # Check host
550 if assert_same_host and not self.is_same_host(url):
551 raise HostChangedError(self, url, retries)
552
553 conn = None
554
555 # Track whether `conn` needs to be released before
556 # returning/raising/recursing. Update this variable if necessary, and
557 # leave `release_conn` constant throughout the function. That way, if
558 # the function recurses, the original value of `release_conn` will be
559 # passed down into the recursive call, and its value will be respected.
560 #
561 # See issue #651 [1] for details.
562 #
563 # [1] <https://github.com/shazow/urllib3/issues/651>
564 release_this_conn = release_conn
565
566 # Merge the proxy headers. Only do this in HTTP. We have to copy the
567 # headers dict so we can safely change it without those changes being
568 # reflected in anyone else's copy.
569 if self.scheme == 'http':
570 headers = headers.copy()
571 headers.update(self.proxy_headers)
572
573 # Must keep the exception bound to a separate variable or else Python 3
574 # complains about UnboundLocalError.
575 err = None
576
577 # Keep track of whether we cleanly exited the except block. This
578 # ensures we do proper cleanup in finally.
579 clean_exit = False
580
581 # Rewind body position, if needed. Record current position
582 # for future rewinds in the event of a redirect/retry.
583 body_pos = set_file_position(body, body_pos)
584
585 try:
586 # Request a connection from the queue.
587 timeout_obj = self._get_timeout(timeout)
588 conn = self._get_conn(timeout=pool_timeout)
589
590 conn.timeout = timeout_obj.connect_timeout
591
592 is_new_proxy_conn = self.proxy is not None and not getattr(conn, 'so ck', None)
593 if is_new_proxy_conn:
594 self._prepare_proxy(conn)
595
596 # Make the request on the httplib connection object.
597 httplib_response = self._make_request(conn, method, url,
598 timeout=timeout_obj,
599 body=body, headers=headers,
600 chunked=chunked)
601
602 # If we're going to release the connection in ``finally:``, then
603 # the response doesn't need to know about the connection. Otherwise
604 # it will also try to release it and we'll have a double-release
605 # mess.
606 response_conn = conn if not release_conn else None
607
608 # Pass method to Response for length checking
609 response_kw['request_method'] = method
610
611 # Import httplib's response into our own wrapper object
612 response = self.ResponseCls.from_httplib(httplib_response,
613 pool=self,
614 connection=response_conn,
615 retries=retries,
616 **response_kw)
617
618 # Everything went great!
619 clean_exit = True
620
621 except queue.Empty:
622 # Timed out by queue.
623 raise EmptyPoolError(self, "No pool connections are available.")
624
625 except (BaseSSLError, CertificateError) as e:
626 # Close the connection. If a connection is reused on which there
627 # was a Certificate error, the next request will certainly raise
628 # another Certificate error.
629 clean_exit = False
630 raise SSLError(e)
631
632 except SSLError:
633 # Treat SSLError separately from BaseSSLError to preserve
634 # traceback.
635 clean_exit = False
636 raise
637
638 except (TimeoutError, HTTPException, SocketError, ProtocolError) as e:
639 # Discard the connection for these exceptions. It will be
640 # be replaced during the next _get_conn() call.
641 clean_exit = False
642
643 if isinstance(e, (SocketError, NewConnectionError)) and self.proxy:
644 e = ProxyError('Cannot connect to proxy.', e)
645 elif isinstance(e, (SocketError, HTTPException)):
646 e = ProtocolError('Connection aborted.', e)
647
648 retries = retries.increment(method, url, error=e, _pool=self,
649 _stacktrace=sys.exc_info()[2])
650 retries.sleep()
651
652 # Keep track of the error for the retry warning.
653 err = e
654
655 finally:
656 if not clean_exit:
657 # We hit some kind of exception, handled or otherwise. We need
658 # to throw the connection away unless explicitly told not to.
659 # Close the connection, set the variable to None, and make sure
660 # we put the None back in the pool to avoid leaking it.
661 conn = conn and conn.close()
662 release_this_conn = True
663
664 if release_this_conn:
665 # Put the connection back to be reused. If the connection is
666 # expired then it will be None, which will get replaced with a
667 # fresh connection during _get_conn.
668 self._put_conn(conn)
669
670 if not conn:
671 # Try again
672 log.warning("Retrying (%r) after connection "
673 "broken by '%r': %s", retries, err, url)
674 return self.urlopen(method, url, body, headers, retries,
675 redirect, assert_same_host,
676 timeout=timeout, pool_timeout=pool_timeout,
677 release_conn=release_conn, body_pos=body_pos,
678 **response_kw)
679
680 # Handle redirect?
681 redirect_location = redirect and response.get_redirect_location()
682 if redirect_location:
683 if response.status == 303:
684 method = 'GET'
685
686 try:
687 retries = retries.increment(method, url, response=response, _poo l=self)
688 except MaxRetryError:
689 if retries.raise_on_redirect:
690 # Release the connection for this response, since we're not
691 # returning it to be released manually.
692 response.release_conn()
693 raise
694 return response
695
696 retries.sleep_for_retry(response)
697 log.debug("Redirecting %s -> %s", url, redirect_location)
698 return self.urlopen(
699 method, redirect_location, body, headers,
700 retries=retries, redirect=redirect,
701 assert_same_host=assert_same_host,
702 timeout=timeout, pool_timeout=pool_timeout,
703 release_conn=release_conn, body_pos=body_pos,
704 **response_kw)
705
706 # Check if we should retry the HTTP response.
707 has_retry_after = bool(response.getheader('Retry-After'))
708 if retries.is_retry(method, response.status, has_retry_after):
709 try:
710 retries = retries.increment(method, url, response=response, _poo l=self)
711 except MaxRetryError:
712 if retries.raise_on_status:
713 # Release the connection for this response, since we're not
714 # returning it to be released manually.
715 response.release_conn()
716 raise
717 return response
718 retries.sleep(response)
719 log.debug("Retry: %s", url)
720 return self.urlopen(
721 method, url, body, headers,
722 retries=retries, redirect=redirect,
723 assert_same_host=assert_same_host,
724 timeout=timeout, pool_timeout=pool_timeout,
725 release_conn=release_conn,
726 body_pos=body_pos, **response_kw)
727
728 return response
729
730
731 class HTTPSConnectionPool(HTTPConnectionPool):
732 """
733 Same as :class:`.HTTPConnectionPool`, but HTTPS.
734
735 When Python is compiled with the :mod:`ssl` module, then
736 :class:`.VerifiedHTTPSConnection` is used, which *can* verify certificates,
737 instead of :class:`.HTTPSConnection`.
738
739 :class:`.VerifiedHTTPSConnection` uses one of ``assert_fingerprint``,
740 ``assert_hostname`` and ``host`` in this order to verify connections.
741 If ``assert_hostname`` is False, no verification is done.
742
743 The ``key_file``, ``cert_file``, ``cert_reqs``, ``ca_certs``,
744 ``ca_cert_dir``, and ``ssl_version`` are only used if :mod:`ssl` is
745 available and are fed into :meth:`urllib3.util.ssl_wrap_socket` to upgrade
746 the connection socket into an SSL socket.
747 """
748
749 scheme = 'https'
750 ConnectionCls = HTTPSConnection
751
752 def __init__(self, host, port=None,
753 strict=False, timeout=Timeout.DEFAULT_TIMEOUT, maxsize=1,
754 block=False, headers=None, retries=None,
755 _proxy=None, _proxy_headers=None,
756 key_file=None, cert_file=None, cert_reqs=None,
757 ca_certs=None, ssl_version=None,
758 assert_hostname=None, assert_fingerprint=None,
759 ca_cert_dir=None, **conn_kw):
760
761 HTTPConnectionPool.__init__(self, host, port, strict, timeout, maxsize,
762 block, headers, retries, _proxy, _proxy_head ers,
763 **conn_kw)
764
765 if ca_certs and cert_reqs is None:
766 cert_reqs = 'CERT_REQUIRED'
767
768 self.key_file = key_file
769 self.cert_file = cert_file
770 self.cert_reqs = cert_reqs
771 self.ca_certs = ca_certs
772 self.ca_cert_dir = ca_cert_dir
773 self.ssl_version = ssl_version
774 self.assert_hostname = assert_hostname
775 self.assert_fingerprint = assert_fingerprint
776
777 def _prepare_conn(self, conn):
778 """
779 Prepare the ``connection`` for :meth:`urllib3.util.ssl_wrap_socket`
780 and establish the tunnel if proxy is used.
781 """
782
783 if isinstance(conn, VerifiedHTTPSConnection):
784 conn.set_cert(key_file=self.key_file,
785 cert_file=self.cert_file,
786 cert_reqs=self.cert_reqs,
787 ca_certs=self.ca_certs,
788 ca_cert_dir=self.ca_cert_dir,
789 assert_hostname=self.assert_hostname,
790 assert_fingerprint=self.assert_fingerprint)
791 conn.ssl_version = self.ssl_version
792 return conn
793
794 def _prepare_proxy(self, conn):
795 """
796 Establish tunnel connection early, because otherwise httplib
797 would improperly set Host: header to proxy's IP:port.
798 """
799 # Python 2.7+
800 try:
801 set_tunnel = conn.set_tunnel
802 except AttributeError: # Platform-specific: Python 2.6
803 set_tunnel = conn._set_tunnel
804
805 if sys.version_info <= (2, 6, 4) and not self.proxy_headers: # Python 2 .6.4 and older
806 set_tunnel(self.host, self.port)
807 else:
808 set_tunnel(self.host, self.port, self.proxy_headers)
809
810 conn.connect()
811
812 def _new_conn(self):
813 """
814 Return a fresh :class:`httplib.HTTPSConnection`.
815 """
816 self.num_connections += 1
817 log.debug("Starting new HTTPS connection (%d): %s",
818 self.num_connections, self.host)
819
820 if not self.ConnectionCls or self.ConnectionCls is DummyConnection:
821 raise SSLError("Can't connect to HTTPS URL because the SSL "
822 "module is not available.")
823
824 actual_host = self.host
825 actual_port = self.port
826 if self.proxy is not None:
827 actual_host = self.proxy.host
828 actual_port = self.proxy.port
829
830 conn = self.ConnectionCls(host=actual_host, port=actual_port,
831 timeout=self.timeout.connect_timeout,
832 strict=self.strict, **self.conn_kw)
833
834 return self._prepare_conn(conn)
835
836 def _validate_conn(self, conn):
837 """
838 Called right before a request is made, after the socket is created.
839 """
840 super(HTTPSConnectionPool, self)._validate_conn(conn)
841
842 # Force connect early to allow us to validate the connection.
843 if not getattr(conn, 'sock', None): # AppEngine might not have `.sock`
844 conn.connect()
845
846 if not conn.is_verified:
847 warnings.warn((
848 'Unverified HTTPS request is being made. '
849 'Adding certificate verification is strongly advised. See: '
850 'https://urllib3.readthedocs.io/en/latest/advanced-usage.html'
851 '#ssl-warnings'),
852 InsecureRequestWarning)
853
854
855 def connection_from_url(url, **kw):
856 """
857 Given a url, return an :class:`.ConnectionPool` instance of its host.
858
859 This is a shortcut for not having to parse out the scheme, host, and port
860 of the url before creating an :class:`.ConnectionPool` instance.
861
862 :param url:
863 Absolute URL string that must include the scheme. Port is optional.
864
865 :param \\**kw:
866 Passes additional parameters to the constructor of the appropriate
867 :class:`.ConnectionPool`. Useful for specifying things like
868 timeout, maxsize, headers, etc.
869
870 Example::
871
872 >>> conn = connection_from_url('http://google.com/')
873 >>> r = conn.request('GET', '/')
874 """
875 scheme, host, port = get_host(url)
876 port = port or port_by_scheme.get(scheme, 80)
877 if scheme == 'https':
878 return HTTPSConnectionPool(host, port=port, **kw)
879 else:
880 return HTTPConnectionPool(host, port=port, **kw)
881
882
883 def _ipv6_host(host):
884 """
885 Process IPv6 address literals
886 """
887
888 # httplib doesn't like it when we include brackets in IPv6 addresses
889 # Specifically, if we include brackets but also pass the port then
890 # httplib crazily doubles up the square brackets on the Host header.
891 # Instead, we need to make sure we never pass ``None`` as the port.
892 # However, for backward compatibility reasons we can't actually
893 # *assert* that. See http://bugs.python.org/issue28539
894 #
895 # Also if an IPv6 address literal has a zone identifier, the
896 # percent sign might be URIencoded, convert it back into ASCII
897 if host.startswith('[') and host.endswith(']'):
898 host = host.replace('%25', '%').strip('[]')
899 return host
OLDNEW
« no previous file with comments | « third_party/google-endpoints/urllib3/connection.py ('k') | third_party/google-endpoints/urllib3/contrib/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698