1"""
2requests.adapters
3~~~~~~~~~~~~~~~~~
4
5This module contains the transport adapters that Requests uses to define
6and maintain connections.
7"""
8
9import os.path
10import socket # noqa: F401
11import typing
12import warnings
13
14from urllib3.exceptions import ClosedPoolError, ConnectTimeoutError
15from urllib3.exceptions import HTTPError as _HTTPError
16from urllib3.exceptions import InvalidHeader as _InvalidHeader
17from urllib3.exceptions import (
18 LocationValueError,
19 MaxRetryError,
20 NewConnectionError,
21 ProtocolError,
22)
23from urllib3.exceptions import ProxyError as _ProxyError
24from urllib3.exceptions import ReadTimeoutError, ResponseError
25from urllib3.exceptions import SSLError as _SSLError
26from urllib3.poolmanager import PoolManager, proxy_from_url
27from urllib3.util import Timeout as TimeoutSauce
28from urllib3.util import parse_url
29from urllib3.util.retry import Retry
30from urllib3.util.ssl_ import create_urllib3_context
31
32from .auth import _basic_auth_str
33from .compat import basestring, urlparse
34from .cookies import extract_cookies_to_jar
35from .exceptions import (
36 ConnectionError,
37 ConnectTimeout,
38 InvalidHeader,
39 InvalidProxyURL,
40 InvalidSchema,
41 InvalidURL,
42 ProxyError,
43 ReadTimeout,
44 RetryError,
45 SSLError,
46)
47from .models import Response
48from .structures import CaseInsensitiveDict
49from .utils import (
50 DEFAULT_CA_BUNDLE_PATH,
51 extract_zipped_paths,
52 get_auth_from_url,
53 get_encoding_from_headers,
54 prepend_scheme_if_needed,
55 select_proxy,
56 urldefragauth,
57)
58
59try:
60 from urllib3.contrib.socks import SOCKSProxyManager
61except ImportError:
62
63 def SOCKSProxyManager(*args, **kwargs):
64 raise InvalidSchema("Missing dependencies for SOCKS support.")
65
66
67if typing.TYPE_CHECKING:
68 from .models import PreparedRequest
69
70
71DEFAULT_POOLBLOCK = False
72DEFAULT_POOLSIZE = 10
73DEFAULT_RETRIES = 0
74DEFAULT_POOL_TIMEOUT = None
75
76
77try:
78 import ssl # noqa: F401
79
80 _preloaded_ssl_context = create_urllib3_context()
81 _preloaded_ssl_context.load_verify_locations(
82 extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH)
83 )
84except ImportError:
85 # Bypass default SSLContext creation when Python
86 # interpreter isn't built with the ssl module.
87 _preloaded_ssl_context = None
88
89
90def _urllib3_request_context(
91 request: "PreparedRequest",
92 verify: "bool | str | None",
93 client_cert: "typing.Tuple[str, str] | str | None",
94 poolmanager: "PoolManager",
95) -> "(typing.Dict[str, typing.Any], typing.Dict[str, typing.Any])":
96 host_params = {}
97 pool_kwargs = {}
98 parsed_request_url = urlparse(request.url)
99 scheme = parsed_request_url.scheme.lower()
100 port = parsed_request_url.port
101
102 # Determine if we have and should use our default SSLContext
103 # to optimize performance on standard requests.
104 poolmanager_kwargs = getattr(poolmanager, "connection_pool_kw", {})
105 has_poolmanager_ssl_context = poolmanager_kwargs.get("ssl_context")
106 should_use_default_ssl_context = (
107 _preloaded_ssl_context is not None and not has_poolmanager_ssl_context
108 )
109
110 cert_reqs = "CERT_REQUIRED"
111 if verify is False:
112 cert_reqs = "CERT_NONE"
113 elif verify is True and should_use_default_ssl_context:
114 pool_kwargs["ssl_context"] = _preloaded_ssl_context
115 elif isinstance(verify, str):
116 if not os.path.isdir(verify):
117 pool_kwargs["ca_certs"] = verify
118 else:
119 pool_kwargs["ca_cert_dir"] = verify
120 pool_kwargs["cert_reqs"] = cert_reqs
121 if client_cert is not None:
122 if isinstance(client_cert, tuple) and len(client_cert) == 2:
123 pool_kwargs["cert_file"] = client_cert[0]
124 pool_kwargs["key_file"] = client_cert[1]
125 else:
126 # According to our docs, we allow users to specify just the client
127 # cert path
128 pool_kwargs["cert_file"] = client_cert
129 host_params = {
130 "scheme": scheme,
131 "host": parsed_request_url.hostname,
132 "port": port,
133 }
134 return host_params, pool_kwargs
135
136
137class BaseAdapter:
138 """The Base Transport Adapter"""
139
140 def __init__(self):
141 super().__init__()
142
143 def send(
144 self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
145 ):
146 """Sends PreparedRequest object. Returns Response object.
147
148 :param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
149 :param stream: (optional) Whether to stream the request content.
150 :param timeout: (optional) How long to wait for the server to send
151 data before giving up, as a float, or a :ref:`(connect timeout,
152 read timeout) <timeouts>` tuple.
153 :type timeout: float or tuple
154 :param verify: (optional) Either a boolean, in which case it controls whether we verify
155 the server's TLS certificate, or a string, in which case it must be a path
156 to a CA bundle to use
157 :param cert: (optional) Any user-provided SSL certificate to be trusted.
158 :param proxies: (optional) The proxies dictionary to apply to the request.
159 """
160 raise NotImplementedError
161
162 def close(self):
163 """Cleans up adapter specific items."""
164 raise NotImplementedError
165
166
167class HTTPAdapter(BaseAdapter):
168 """The built-in HTTP Adapter for urllib3.
169
170 Provides a general-case interface for Requests sessions to contact HTTP and
171 HTTPS urls by implementing the Transport Adapter interface. This class will
172 usually be created by the :class:`Session <Session>` class under the
173 covers.
174
175 :param pool_connections: The number of urllib3 connection pools to cache.
176 :param pool_maxsize: The maximum number of connections to save in the pool.
177 :param max_retries: The maximum number of retries each connection
178 should attempt. Note, this applies only to failed DNS lookups, socket
179 connections and connection timeouts, never to requests where data has
180 made it to the server. By default, Requests does not retry failed
181 connections. If you need granular control over the conditions under
182 which we retry a request, import urllib3's ``Retry`` class and pass
183 that instead.
184 :param pool_block: Whether the connection pool should block for connections.
185
186 Usage::
187
188 >>> import requests
189 >>> s = requests.Session()
190 >>> a = requests.adapters.HTTPAdapter(max_retries=3)
191 >>> s.mount('http://', a)
192 """
193
194 __attrs__ = [
195 "max_retries",
196 "config",
197 "_pool_connections",
198 "_pool_maxsize",
199 "_pool_block",
200 ]
201
202 def __init__(
203 self,
204 pool_connections=DEFAULT_POOLSIZE,
205 pool_maxsize=DEFAULT_POOLSIZE,
206 max_retries=DEFAULT_RETRIES,
207 pool_block=DEFAULT_POOLBLOCK,
208 ):
209 if max_retries == DEFAULT_RETRIES:
210 self.max_retries = Retry(0, read=False)
211 else:
212 self.max_retries = Retry.from_int(max_retries)
213 self.config = {}
214 self.proxy_manager = {}
215
216 super().__init__()
217
218 self._pool_connections = pool_connections
219 self._pool_maxsize = pool_maxsize
220 self._pool_block = pool_block
221
222 self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block)
223
224 def __getstate__(self):
225 return {attr: getattr(self, attr, None) for attr in self.__attrs__}
226
227 def __setstate__(self, state):
228 # Can't handle by adding 'proxy_manager' to self.__attrs__ because
229 # self.poolmanager uses a lambda function, which isn't pickleable.
230 self.proxy_manager = {}
231 self.config = {}
232
233 for attr, value in state.items():
234 setattr(self, attr, value)
235
236 self.init_poolmanager(
237 self._pool_connections, self._pool_maxsize, block=self._pool_block
238 )
239
240 def init_poolmanager(
241 self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool_kwargs
242 ):
243 """Initializes a urllib3 PoolManager.
244
245 This method should not be called from user code, and is only
246 exposed for use when subclassing the
247 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
248
249 :param connections: The number of urllib3 connection pools to cache.
250 :param maxsize: The maximum number of connections to save in the pool.
251 :param block: Block when no free connections are available.
252 :param pool_kwargs: Extra keyword arguments used to initialize the Pool Manager.
253 """
254 # save these values for pickling
255 self._pool_connections = connections
256 self._pool_maxsize = maxsize
257 self._pool_block = block
258
259 self.poolmanager = PoolManager(
260 num_pools=connections,
261 maxsize=maxsize,
262 block=block,
263 **pool_kwargs,
264 )
265
266 def proxy_manager_for(self, proxy, **proxy_kwargs):
267 """Return urllib3 ProxyManager for the given proxy.
268
269 This method should not be called from user code, and is only
270 exposed for use when subclassing the
271 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
272
273 :param proxy: The proxy to return a urllib3 ProxyManager for.
274 :param proxy_kwargs: Extra keyword arguments used to configure the Proxy Manager.
275 :returns: ProxyManager
276 :rtype: urllib3.ProxyManager
277 """
278 if proxy in self.proxy_manager:
279 manager = self.proxy_manager[proxy]
280 elif proxy.lower().startswith("socks"):
281 username, password = get_auth_from_url(proxy)
282 manager = self.proxy_manager[proxy] = SOCKSProxyManager(
283 proxy,
284 username=username,
285 password=password,
286 num_pools=self._pool_connections,
287 maxsize=self._pool_maxsize,
288 block=self._pool_block,
289 **proxy_kwargs,
290 )
291 else:
292 proxy_headers = self.proxy_headers(proxy)
293 manager = self.proxy_manager[proxy] = proxy_from_url(
294 proxy,
295 proxy_headers=proxy_headers,
296 num_pools=self._pool_connections,
297 maxsize=self._pool_maxsize,
298 block=self._pool_block,
299 **proxy_kwargs,
300 )
301
302 return manager
303
304 def cert_verify(self, conn, url, verify, cert):
305 """Verify a SSL certificate. This method should not be called from user
306 code, and is only exposed for use when subclassing the
307 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
308
309 :param conn: The urllib3 connection object associated with the cert.
310 :param url: The requested URL.
311 :param verify: Either a boolean, in which case it controls whether we verify
312 the server's TLS certificate, or a string, in which case it must be a path
313 to a CA bundle to use
314 :param cert: The SSL certificate to verify.
315 """
316 if url.lower().startswith("https") and verify:
317 conn.cert_reqs = "CERT_REQUIRED"
318
319 # Only load the CA certificates if 'verify' is a string indicating the CA bundle to use.
320 # Otherwise, if verify is a boolean, we don't load anything since
321 # the connection will be using a context with the default certificates already loaded,
322 # and this avoids a call to the slow load_verify_locations()
323 if verify is not True:
324 # `verify` must be a str with a path then
325 cert_loc = verify
326
327 if not os.path.exists(cert_loc):
328 raise OSError(
329 f"Could not find a suitable TLS CA certificate bundle, "
330 f"invalid path: {cert_loc}"
331 )
332
333 if not os.path.isdir(cert_loc):
334 conn.ca_certs = cert_loc
335 else:
336 conn.ca_cert_dir = cert_loc
337 else:
338 conn.cert_reqs = "CERT_NONE"
339 conn.ca_certs = None
340 conn.ca_cert_dir = None
341
342 if cert:
343 if not isinstance(cert, basestring):
344 conn.cert_file = cert[0]
345 conn.key_file = cert[1]
346 else:
347 conn.cert_file = cert
348 conn.key_file = None
349 if conn.cert_file and not os.path.exists(conn.cert_file):
350 raise OSError(
351 f"Could not find the TLS certificate file, "
352 f"invalid path: {conn.cert_file}"
353 )
354 if conn.key_file and not os.path.exists(conn.key_file):
355 raise OSError(
356 f"Could not find the TLS key file, invalid path: {conn.key_file}"
357 )
358
359 def build_response(self, req, resp):
360 """Builds a :class:`Response <requests.Response>` object from a urllib3
361 response. This should not be called from user code, and is only exposed
362 for use when subclassing the
363 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`
364
365 :param req: The :class:`PreparedRequest <PreparedRequest>` used to generate the response.
366 :param resp: The urllib3 response object.
367 :rtype: requests.Response
368 """
369 response = Response()
370
371 # Fallback to None if there's no status_code, for whatever reason.
372 response.status_code = getattr(resp, "status", None)
373
374 # Make headers case-insensitive.
375 response.headers = CaseInsensitiveDict(getattr(resp, "headers", {}))
376
377 # Set encoding.
378 response.encoding = get_encoding_from_headers(response.headers)
379 response.raw = resp
380 response.reason = response.raw.reason
381
382 if isinstance(req.url, bytes):
383 response.url = req.url.decode("utf-8")
384 else:
385 response.url = req.url
386
387 # Add new cookies from the server.
388 extract_cookies_to_jar(response.cookies, req, resp)
389
390 # Give the Response some context.
391 response.request = req
392 response.connection = self
393
394 return response
395
396 def build_connection_pool_key_attributes(self, request, verify, cert=None):
397 """Build the PoolKey attributes used by urllib3 to return a connection.
398
399 This looks at the PreparedRequest, the user-specified verify value,
400 and the value of the cert parameter to determine what PoolKey values
401 to use to select a connection from a given urllib3 Connection Pool.
402
403 The SSL related pool key arguments are not consistently set. As of
404 this writing, use the following to determine what keys may be in that
405 dictionary:
406
407 * If ``verify`` is ``True``, ``"ssl_context"`` will be set and will be the
408 default Requests SSL Context
409 * If ``verify`` is ``False``, ``"ssl_context"`` will not be set but
410 ``"cert_reqs"`` will be set
411 * If ``verify`` is a string, (i.e., it is a user-specified trust bundle)
412 ``"ca_certs"`` will be set if the string is not a directory recognized
413 by :py:func:`os.path.isdir`, otherwise ``"ca_certs_dir"`` will be
414 set.
415 * If ``"cert"`` is specified, ``"cert_file"`` will always be set. If
416 ``"cert"`` is a tuple with a second item, ``"key_file"`` will also
417 be present
418
419 To override these settings, one may subclass this class, call this
420 method and use the above logic to change parameters as desired. For
421 example, if one wishes to use a custom :py:class:`ssl.SSLContext` one
422 must both set ``"ssl_context"`` and based on what else they require,
423 alter the other keys to ensure the desired behaviour.
424
425 :param request:
426 The PreparedReqest being sent over the connection.
427 :type request:
428 :class:`~requests.models.PreparedRequest`
429 :param verify:
430 Either a boolean, in which case it controls whether
431 we verify the server's TLS certificate, or a string, in which case it
432 must be a path to a CA bundle to use.
433 :param cert:
434 (optional) Any user-provided SSL certificate for client
435 authentication (a.k.a., mTLS). This may be a string (i.e., just
436 the path to a file which holds both certificate and key) or a
437 tuple of length 2 with the certificate file path and key file
438 path.
439 :returns:
440 A tuple of two dictionaries. The first is the "host parameters"
441 portion of the Pool Key including scheme, hostname, and port. The
442 second is a dictionary of SSLContext related parameters.
443 """
444 return _urllib3_request_context(request, verify, cert, self.poolmanager)
445
446 def get_connection_with_tls_context(self, request, verify, proxies=None, cert=None):
447 """Returns a urllib3 connection for the given request and TLS settings.
448 This should not be called from user code, and is only exposed for use
449 when subclassing the :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
450
451 :param request:
452 The :class:`PreparedRequest <PreparedRequest>` object to be sent
453 over the connection.
454 :param verify:
455 Either a boolean, in which case it controls whether we verify the
456 server's TLS certificate, or a string, in which case it must be a
457 path to a CA bundle to use.
458 :param proxies:
459 (optional) The proxies dictionary to apply to the request.
460 :param cert:
461 (optional) Any user-provided SSL certificate to be used for client
462 authentication (a.k.a., mTLS).
463 :rtype:
464 urllib3.ConnectionPool
465 """
466 proxy = select_proxy(request.url, proxies)
467 try:
468 host_params, pool_kwargs = self.build_connection_pool_key_attributes(
469 request,
470 verify,
471 cert,
472 )
473 except ValueError as e:
474 raise InvalidURL(e, request=request)
475 if proxy:
476 proxy = prepend_scheme_if_needed(proxy, "http")
477 proxy_url = parse_url(proxy)
478 if not proxy_url.host:
479 raise InvalidProxyURL(
480 "Please check proxy URL. It is malformed "
481 "and could be missing the host."
482 )
483 proxy_manager = self.proxy_manager_for(proxy)
484 conn = proxy_manager.connection_from_host(
485 **host_params, pool_kwargs=pool_kwargs
486 )
487 else:
488 # Only scheme should be lower case
489 conn = self.poolmanager.connection_from_host(
490 **host_params, pool_kwargs=pool_kwargs
491 )
492
493 return conn
494
495 def get_connection(self, url, proxies=None):
496 """DEPRECATED: Users should move to `get_connection_with_tls_context`
497 for all subclasses of HTTPAdapter using Requests>=2.32.2.
498
499 Returns a urllib3 connection for the given URL. This should not be
500 called from user code, and is only exposed for use when subclassing the
501 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
502
503 :param url: The URL to connect to.
504 :param proxies: (optional) A Requests-style dictionary of proxies used on this request.
505 :rtype: urllib3.ConnectionPool
506 """
507 warnings.warn(
508 (
509 "`get_connection` has been deprecated in favor of "
510 "`get_connection_with_tls_context`. Custom HTTPAdapter subclasses "
511 "will need to migrate for Requests>=2.32.2. Please see "
512 "https://github.com/psf/requests/pull/6710 for more details."
513 ),
514 DeprecationWarning,
515 )
516 proxy = select_proxy(url, proxies)
517
518 if proxy:
519 proxy = prepend_scheme_if_needed(proxy, "http")
520 proxy_url = parse_url(proxy)
521 if not proxy_url.host:
522 raise InvalidProxyURL(
523 "Please check proxy URL. It is malformed "
524 "and could be missing the host."
525 )
526 proxy_manager = self.proxy_manager_for(proxy)
527 conn = proxy_manager.connection_from_url(url)
528 else:
529 # Only scheme should be lower case
530 parsed = urlparse(url)
531 url = parsed.geturl()
532 conn = self.poolmanager.connection_from_url(url)
533
534 return conn
535
536 def close(self):
537 """Disposes of any internal state.
538
539 Currently, this closes the PoolManager and any active ProxyManager,
540 which closes any pooled connections.
541 """
542 self.poolmanager.clear()
543 for proxy in self.proxy_manager.values():
544 proxy.clear()
545
546 def request_url(self, request, proxies):
547 """Obtain the url to use when making the final request.
548
549 If the message is being sent through a HTTP proxy, the full URL has to
550 be used. Otherwise, we should only use the path portion of the URL.
551
552 This should not be called from user code, and is only exposed for use
553 when subclassing the
554 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
555
556 :param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
557 :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs.
558 :rtype: str
559 """
560 proxy = select_proxy(request.url, proxies)
561 scheme = urlparse(request.url).scheme
562
563 is_proxied_http_request = proxy and scheme != "https"
564 using_socks_proxy = False
565 if proxy:
566 proxy_scheme = urlparse(proxy).scheme.lower()
567 using_socks_proxy = proxy_scheme.startswith("socks")
568
569 url = request.path_url
570 if url.startswith("//"): # Don't confuse urllib3
571 url = f"/{url.lstrip('/')}"
572
573 if is_proxied_http_request and not using_socks_proxy:
574 url = urldefragauth(request.url)
575
576 return url
577
578 def add_headers(self, request, **kwargs):
579 """Add any headers needed by the connection. As of v2.0 this does
580 nothing by default, but is left for overriding by users that subclass
581 the :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
582
583 This should not be called from user code, and is only exposed for use
584 when subclassing the
585 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
586
587 :param request: The :class:`PreparedRequest <PreparedRequest>` to add headers to.
588 :param kwargs: The keyword arguments from the call to send().
589 """
590 pass
591
592 def proxy_headers(self, proxy):
593 """Returns a dictionary of the headers to add to any request sent
594 through a proxy. This works with urllib3 magic to ensure that they are
595 correctly sent to the proxy, rather than in a tunnelled request if
596 CONNECT is being used.
597
598 This should not be called from user code, and is only exposed for use
599 when subclassing the
600 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
601
602 :param proxy: The url of the proxy being used for this request.
603 :rtype: dict
604 """
605 headers = {}
606 username, password = get_auth_from_url(proxy)
607
608 if username:
609 headers["Proxy-Authorization"] = _basic_auth_str(username, password)
610
611 return headers
612
613 def send(
614 self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
615 ):
616 """Sends PreparedRequest object. Returns Response object.
617
618 :param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
619 :param stream: (optional) Whether to stream the request content.
620 :param timeout: (optional) How long to wait for the server to send
621 data before giving up, as a float, or a :ref:`(connect timeout,
622 read timeout) <timeouts>` tuple.
623 :type timeout: float or tuple or urllib3 Timeout object
624 :param verify: (optional) Either a boolean, in which case it controls whether
625 we verify the server's TLS certificate, or a string, in which case it
626 must be a path to a CA bundle to use
627 :param cert: (optional) Any user-provided SSL certificate to be trusted.
628 :param proxies: (optional) The proxies dictionary to apply to the request.
629 :rtype: requests.Response
630 """
631
632 try:
633 conn = self.get_connection_with_tls_context(
634 request, verify, proxies=proxies, cert=cert
635 )
636 except LocationValueError as e:
637 raise InvalidURL(e, request=request)
638
639 self.cert_verify(conn, request.url, verify, cert)
640 url = self.request_url(request, proxies)
641 self.add_headers(
642 request,
643 stream=stream,
644 timeout=timeout,
645 verify=verify,
646 cert=cert,
647 proxies=proxies,
648 )
649
650 chunked = not (request.body is None or "Content-Length" in request.headers)
651
652 if isinstance(timeout, tuple):
653 try:
654 connect, read = timeout
655 timeout = TimeoutSauce(connect=connect, read=read)
656 except ValueError:
657 raise ValueError(
658 f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
659 f"or a single float to set both timeouts to the same value."
660 )
661 elif isinstance(timeout, TimeoutSauce):
662 pass
663 else:
664 timeout = TimeoutSauce(connect=timeout, read=timeout)
665
666 try:
667 resp = conn.urlopen(
668 method=request.method,
669 url=url,
670 body=request.body,
671 headers=request.headers,
672 redirect=False,
673 assert_same_host=False,
674 preload_content=False,
675 decode_content=False,
676 retries=self.max_retries,
677 timeout=timeout,
678 chunked=chunked,
679 )
680
681 except (ProtocolError, OSError) as err:
682 raise ConnectionError(err, request=request)
683
684 except MaxRetryError as e:
685 if isinstance(e.reason, ConnectTimeoutError):
686 # TODO: Remove this in 3.0.0: see #2811
687 if not isinstance(e.reason, NewConnectionError):
688 raise ConnectTimeout(e, request=request)
689
690 if isinstance(e.reason, ResponseError):
691 raise RetryError(e, request=request)
692
693 if isinstance(e.reason, _ProxyError):
694 raise ProxyError(e, request=request)
695
696 if isinstance(e.reason, _SSLError):
697 # This branch is for urllib3 v1.22 and later.
698 raise SSLError(e, request=request)
699
700 raise ConnectionError(e, request=request)
701
702 except ClosedPoolError as e:
703 raise ConnectionError(e, request=request)
704
705 except _ProxyError as e:
706 raise ProxyError(e)
707
708 except (_SSLError, _HTTPError) as e:
709 if isinstance(e, _SSLError):
710 # This branch is for urllib3 versions earlier than v1.22
711 raise SSLError(e, request=request)
712 elif isinstance(e, ReadTimeoutError):
713 raise ReadTimeout(e, request=request)
714 elif isinstance(e, _InvalidHeader):
715 raise InvalidHeader(e, request=request)
716 else:
717 raise
718
719 return self.build_response(request, resp)