1from __future__ import annotations 
    2 
    3import errno 
    4import logging 
    5import queue 
    6import sys 
    7import typing 
    8import warnings 
    9import weakref 
    10from socket import timeout as SocketTimeout 
    11from types import TracebackType 
    12 
    13from ._base_connection import _TYPE_BODY 
    14from ._collections import HTTPHeaderDict 
    15from ._request_methods import RequestMethods 
    16from .connection import ( 
    17    BaseSSLError, 
    18    BrokenPipeError, 
    19    DummyConnection, 
    20    HTTPConnection, 
    21    HTTPException, 
    22    HTTPSConnection, 
    23    ProxyConfig, 
    24    _wrap_proxy_error, 
    25) 
    26from .connection import port_by_scheme as port_by_scheme 
    27from .exceptions import ( 
    28    ClosedPoolError, 
    29    EmptyPoolError, 
    30    FullPoolError, 
    31    HostChangedError, 
    32    InsecureRequestWarning, 
    33    LocationValueError, 
    34    MaxRetryError, 
    35    NewConnectionError, 
    36    ProtocolError, 
    37    ProxyError, 
    38    ReadTimeoutError, 
    39    SSLError, 
    40    TimeoutError, 
    41) 
    42from .response import BaseHTTPResponse 
    43from .util.connection import is_connection_dropped 
    44from .util.proxy import connection_requires_http_tunnel 
    45from .util.request import _TYPE_BODY_POSITION, set_file_position 
    46from .util.retry import Retry 
    47from .util.ssl_match_hostname import CertificateError 
    48from .util.timeout import _DEFAULT_TIMEOUT, _TYPE_DEFAULT, Timeout 
    49from .util.url import Url, _encode_target 
    50from .util.url import _normalize_host as normalize_host 
    51from .util.url import parse_url 
    52from .util.util import to_str 
    53 
    54if typing.TYPE_CHECKING: 
    55    import ssl 
    56 
    57    from typing_extensions import Self 
    58 
    59    from ._base_connection import BaseHTTPConnection, BaseHTTPSConnection 
    60 
    61log = logging.getLogger(__name__) 
    62 
    63_TYPE_TIMEOUT = typing.Union[Timeout, float, _TYPE_DEFAULT, None] 
    64 
    65 
    66# Pool objects 
    67class ConnectionPool: 
    68    """ 
    69    Base class for all connection pools, such as 
    70    :class:`.HTTPConnectionPool` and :class:`.HTTPSConnectionPool`. 
    71 
    72    .. note:: 
    73       ConnectionPool.urlopen() does not normalize or percent-encode target URIs 
    74       which is useful if your target server doesn't support percent-encoded 
    75       target URIs. 
    76    """ 
    77 
    78    scheme: str | None = None 
    79    QueueCls = queue.LifoQueue 
    80 
    81    def __init__(self, host: str, port: int | None = None) -> None: 
    82        if not host: 
    83            raise LocationValueError("No host specified.") 
    84 
    85        self.host = _normalize_host(host, scheme=self.scheme) 
    86        self.port = port 
    87 
    88        # This property uses 'normalize_host()' (not '_normalize_host()') 
    89        # to avoid removing square braces around IPv6 addresses. 
    90        # This value is sent to `HTTPConnection.set_tunnel()` if called 
    91        # because square braces are required for HTTP CONNECT tunneling. 
    92        self._tunnel_host = normalize_host(host, scheme=self.scheme).lower() 
    93 
    94    def __str__(self) -> str: 
    95        return f"{type(self).__name__}(host={self.host!r}, port={self.port!r})" 
    96 
    97    def __enter__(self) -> Self: 
    98        return self 
    99 
    100    def __exit__( 
    101        self, 
    102        exc_type: type[BaseException] | None, 
    103        exc_val: BaseException | None, 
    104        exc_tb: TracebackType | None, 
    105    ) -> typing.Literal[False]: 
    106        self.close() 
    107        # Return False to re-raise any potential exceptions 
    108        return False 
    109 
    110    def close(self) -> None: 
    111        """ 
    112        Close all pooled connections and disable the pool. 
    113        """ 
    114 
    115 
    116# This is taken from http://hg.python.org/cpython/file/7aaba721ebc0/Lib/socket.py#l252 
    117_blocking_errnos = {errno.EAGAIN, errno.EWOULDBLOCK} 
    118 
    119 
    120class HTTPConnectionPool(ConnectionPool, RequestMethods): 
    121    """ 
    122    Thread-safe connection pool for one host. 
    123 
    124    :param host: 
    125        Host used for this HTTP Connection (e.g. "localhost"), passed into 
    126        :class:`http.client.HTTPConnection`. 
    127 
    128    :param port: 
    129        Port used for this HTTP Connection (None is equivalent to 80), passed 
    130        into :class:`http.client.HTTPConnection`. 
    131 
    132    :param timeout: 
    133        Socket timeout in seconds for each individual connection. This can 
    134        be a float or integer, which sets the timeout for the HTTP request, 
    135        or an instance of :class:`urllib3.util.Timeout` which gives you more 
    136        fine-grained control over request timeouts. After the constructor has 
    137        been parsed, this is always a `urllib3.util.Timeout` object. 
    138 
    139    :param maxsize: 
    140        Number of connections to save that can be reused. More than 1 is useful 
    141        in multithreaded situations. If ``block`` is set to False, more 
    142        connections will be created but they will not be saved once they've 
    143        been used. 
    144 
    145    :param block: 
    146        If set to True, no more than ``maxsize`` connections will be used at 
    147        a time. When no free connections are available, the call will block 
    148        until a connection has been released. This is a useful side effect for 
    149        particular multithreaded situations where one does not want to use more 
    150        than maxsize connections per host to prevent flooding. 
    151 
    152    :param headers: 
    153        Headers to include with all requests, unless other headers are given 
    154        explicitly. 
    155 
    156    :param retries: 
    157        Retry configuration to use by default with requests in this pool. 
    158 
    159    :param _proxy: 
    160        Parsed proxy URL, should not be used directly, instead, see 
    161        :class:`urllib3.ProxyManager` 
    162 
    163    :param _proxy_headers: 
    164        A dictionary with proxy headers, should not be used directly, 
    165        instead, see :class:`urllib3.ProxyManager` 
    166 
    167    :param \\**conn_kw: 
    168        Additional parameters are used to create fresh :class:`urllib3.connection.HTTPConnection`, 
    169        :class:`urllib3.connection.HTTPSConnection` instances. 
    170    """ 
    171 
    172    scheme = "http" 
    173    ConnectionCls: type[BaseHTTPConnection] | type[BaseHTTPSConnection] = HTTPConnection 
    174 
    175    def __init__( 
    176        self, 
    177        host: str, 
    178        port: int | None = None, 
    179        timeout: _TYPE_TIMEOUT | None = _DEFAULT_TIMEOUT, 
    180        maxsize: int = 1, 
    181        block: bool = False, 
    182        headers: typing.Mapping[str, str] | None = None, 
    183        retries: Retry | bool | int | None = None, 
    184        _proxy: Url | None = None, 
    185        _proxy_headers: typing.Mapping[str, str] | None = None, 
    186        _proxy_config: ProxyConfig | None = None, 
    187        **conn_kw: typing.Any, 
    188    ): 
    189        ConnectionPool.__init__(self, host, port) 
    190        RequestMethods.__init__(self, headers) 
    191 
    192        if not isinstance(timeout, Timeout): 
    193            timeout = Timeout.from_float(timeout) 
    194 
    195        if retries is None: 
    196            retries = Retry.DEFAULT 
    197 
    198        self.timeout = timeout 
    199        self.retries = retries 
    200 
    201        self.pool: queue.LifoQueue[typing.Any] | None = self.QueueCls(maxsize) 
    202        self.block = block 
    203 
    204        self.proxy = _proxy 
    205        self.proxy_headers = _proxy_headers or {} 
    206        self.proxy_config = _proxy_config 
    207 
    208        # Fill the queue up so that doing get() on it will block properly 
    209        for _ in range(maxsize): 
    210            self.pool.put(None) 
    211 
    212        # These are mostly for testing and debugging purposes. 
    213        self.num_connections = 0 
    214        self.num_requests = 0 
    215        self.conn_kw = conn_kw 
    216 
    217        if self.proxy: 
    218            # Enable Nagle's algorithm for proxies, to avoid packet fragmentation. 
    219            # We cannot know if the user has added default socket options, so we cannot replace the 
    220            # list. 
    221            self.conn_kw.setdefault("socket_options", []) 
    222 
    223            self.conn_kw["proxy"] = self.proxy 
    224            self.conn_kw["proxy_config"] = self.proxy_config 
    225 
    226        # Do not pass 'self' as callback to 'finalize'. 
    227        # Then the 'finalize' would keep an endless living (leak) to self. 
    228        # By just passing a reference to the pool allows the garbage collector 
    229        # to free self if nobody else has a reference to it. 
    230        pool = self.pool 
    231 
    232        # Close all the HTTPConnections in the pool before the 
    233        # HTTPConnectionPool object is garbage collected. 
    234        weakref.finalize(self, _close_pool_connections, pool) 
    235 
    236    def _new_conn(self) -> BaseHTTPConnection: 
    237        """ 
    238        Return a fresh :class:`HTTPConnection`. 
    239        """ 
    240        self.num_connections += 1 
    241        log.debug( 
    242            "Starting new HTTP connection (%d): %s:%s", 
    243            self.num_connections, 
    244            self.host, 
    245            self.port or "80", 
    246        ) 
    247 
    248        conn = self.ConnectionCls( 
    249            host=self.host, 
    250            port=self.port, 
    251            timeout=self.timeout.connect_timeout, 
    252            **self.conn_kw, 
    253        ) 
    254        return conn 
    255 
    256    def _get_conn(self, timeout: float | None = None) -> BaseHTTPConnection: 
    257        """ 
    258        Get a connection. Will return a pooled connection if one is available. 
    259 
    260        If no connections are available and :prop:`.block` is ``False``, then a 
    261        fresh connection is returned. 
    262 
    263        :param timeout: 
    264            Seconds to wait before giving up and raising 
    265            :class:`urllib3.exceptions.EmptyPoolError` if the pool is empty and 
    266            :prop:`.block` is ``True``. 
    267        """ 
    268        conn = None 
    269 
    270        if self.pool is None: 
    271            raise ClosedPoolError(self, "Pool is closed.") 
    272 
    273        try: 
    274            conn = self.pool.get(block=self.block, timeout=timeout) 
    275 
    276        except AttributeError:  # self.pool is None 
    277            raise ClosedPoolError(self, "Pool is closed.") from None  # Defensive: 
    278 
    279        except queue.Empty: 
    280            if self.block: 
    281                raise EmptyPoolError( 
    282                    self, 
    283                    "Pool is empty and a new connection can't be opened due to blocking mode.", 
    284                ) from None 
    285            pass  # Oh well, we'll create a new connection then 
    286 
    287        # If this is a persistent connection, check if it got disconnected 
    288        if conn and is_connection_dropped(conn): 
    289            log.debug("Resetting dropped connection: %s", self.host) 
    290            conn.close() 
    291 
    292        return conn or self._new_conn() 
    293 
    294    def _put_conn(self, conn: BaseHTTPConnection | None) -> None: 
    295        """ 
    296        Put a connection back into the pool. 
    297 
    298        :param conn: 
    299            Connection object for the current host and port as returned by 
    300            :meth:`._new_conn` or :meth:`._get_conn`. 
    301 
    302        If the pool is already full, the connection is closed and discarded 
    303        because we exceeded maxsize. If connections are discarded frequently, 
    304        then maxsize should be increased. 
    305 
    306        If the pool is closed, then the connection will be closed and discarded. 
    307        """ 
    308        if self.pool is not None: 
    309            try: 
    310                self.pool.put(conn, block=False) 
    311                return  # Everything is dandy, done. 
    312            except AttributeError: 
    313                # self.pool is None. 
    314                pass 
    315            except queue.Full: 
    316                # Connection never got put back into the pool, close it. 
    317                if conn: 
    318                    conn.close() 
    319 
    320                if self.block: 
    321                    # This should never happen if you got the conn from self._get_conn 
    322                    raise FullPoolError( 
    323                        self, 
    324                        "Pool reached maximum size and no more connections are allowed.", 
    325                    ) from None 
    326 
    327                log.warning( 
    328                    "Connection pool is full, discarding connection: %s. Connection pool size: %s", 
    329                    self.host, 
    330                    self.pool.qsize(), 
    331                ) 
    332 
    333        # Connection never got put back into the pool, close it. 
    334        if conn: 
    335            conn.close() 
    336 
    337    def _validate_conn(self, conn: BaseHTTPConnection) -> None: 
    338        """ 
    339        Called right before a request is made, after the socket is created. 
    340        """ 
    341 
    342    def _prepare_proxy(self, conn: BaseHTTPConnection) -> None: 
    343        # Nothing to do for HTTP connections. 
    344        pass 
    345 
    346    def _get_timeout(self, timeout: _TYPE_TIMEOUT) -> Timeout: 
    347        """Helper that always returns a :class:`urllib3.util.Timeout`""" 
    348        if timeout is _DEFAULT_TIMEOUT: 
    349            return self.timeout.clone() 
    350 
    351        if isinstance(timeout, Timeout): 
    352            return timeout.clone() 
    353        else: 
    354            # User passed us an int/float. This is for backwards compatibility, 
    355            # can be removed later 
    356            return Timeout.from_float(timeout) 
    357 
    358    def _raise_timeout( 
    359        self, 
    360        err: BaseSSLError | OSError | SocketTimeout, 
    361        url: str, 
    362        timeout_value: _TYPE_TIMEOUT | None, 
    363    ) -> None: 
    364        """Is the error actually a timeout? Will raise a ReadTimeout or pass""" 
    365 
    366        if isinstance(err, SocketTimeout): 
    367            raise ReadTimeoutError( 
    368                self, url, f"Read timed out. (read timeout={timeout_value})" 
    369            ) from err 
    370 
    371        # See the above comment about EAGAIN in Python 3. 
    372        if hasattr(err, "errno") and err.errno in _blocking_errnos: 
    373            raise ReadTimeoutError( 
    374                self, url, f"Read timed out. (read timeout={timeout_value})" 
    375            ) from err 
    376 
    377    def _make_request( 
    378        self, 
    379        conn: BaseHTTPConnection, 
    380        method: str, 
    381        url: str, 
    382        body: _TYPE_BODY | None = None, 
    383        headers: typing.Mapping[str, str] | None = None, 
    384        retries: Retry | None = None, 
    385        timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, 
    386        chunked: bool = False, 
    387        response_conn: BaseHTTPConnection | None = None, 
    388        preload_content: bool = True, 
    389        decode_content: bool = True, 
    390        enforce_content_length: bool = True, 
    391    ) -> BaseHTTPResponse: 
    392        """ 
    393        Perform a request on a given urllib connection object taken from our 
    394        pool. 
    395 
    396        :param conn: 
    397            a connection from one of our connection pools 
    398 
    399        :param method: 
    400            HTTP request method (such as GET, POST, PUT, etc.) 
    401 
    402        :param url: 
    403            The URL to perform the request on. 
    404 
    405        :param body: 
    406            Data to send in the request body, either :class:`str`, :class:`bytes`, 
    407            an iterable of :class:`str`/:class:`bytes`, or a file-like object. 
    408 
    409        :param headers: 
    410            Dictionary of custom headers to send, such as User-Agent, 
    411            If-None-Match, etc. If None, pool headers are used. If provided, 
    412            these headers completely replace any pool-specific headers. 
    413 
    414        :param retries: 
    415            Configure the number of retries to allow before raising a 
    416            :class:`~urllib3.exceptions.MaxRetryError` exception. 
    417 
    418            Pass ``None`` to retry until you receive a response. Pass a 
    419            :class:`~urllib3.util.retry.Retry` object for fine-grained control 
    420            over different types of retries. 
    421            Pass an integer number to retry connection errors that many times, 
    422            but no other types of errors. Pass zero to never retry. 
    423 
    424            If ``False``, then retries are disabled and any exception is raised 
    425            immediately. Also, instead of raising a MaxRetryError on redirects, 
    426            the redirect response will be returned. 
    427 
    428        :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. 
    429 
    430        :param timeout: 
    431            If specified, overrides the default timeout for this one 
    432            request. It may be a float (in seconds) or an instance of 
    433            :class:`urllib3.util.Timeout`. 
    434 
    435        :param chunked: 
    436            If True, urllib3 will send the body using chunked transfer 
    437            encoding. Otherwise, urllib3 will send the body using the standard 
    438            content-length form. Defaults to False. 
    439 
    440        :param response_conn: 
    441            Set this to ``None`` if you will handle releasing the connection or 
    442            set the connection to have the response release it. 
    443 
    444        :param preload_content: 
    445          If True, the response's body will be preloaded during construction. 
    446 
    447        :param decode_content: 
    448            If True, will attempt to decode the body based on the 
    449            'content-encoding' header. 
    450 
    451        :param enforce_content_length: 
    452            Enforce content length checking. Body returned by server must match 
    453            value of Content-Length header, if present. Otherwise, raise error. 
    454        """ 
    455        self.num_requests += 1 
    456 
    457        timeout_obj = self._get_timeout(timeout) 
    458        timeout_obj.start_connect() 
    459        conn.timeout = Timeout.resolve_default_timeout(timeout_obj.connect_timeout) 
    460 
    461        try: 
    462            # Trigger any extra validation we need to do. 
    463            try: 
    464                self._validate_conn(conn) 
    465            except (SocketTimeout, BaseSSLError) as e: 
    466                self._raise_timeout(err=e, url=url, timeout_value=conn.timeout) 
    467                raise 
    468 
    469        # _validate_conn() starts the connection to an HTTPS proxy 
    470        # so we need to wrap errors with 'ProxyError' here too. 
    471        except ( 
    472            OSError, 
    473            NewConnectionError, 
    474            TimeoutError, 
    475            BaseSSLError, 
    476            CertificateError, 
    477            SSLError, 
    478        ) as e: 
    479            new_e: Exception = e 
    480            if isinstance(e, (BaseSSLError, CertificateError)): 
    481                new_e = SSLError(e) 
    482            # If the connection didn't successfully connect to it's proxy 
    483            # then there 
    484            if isinstance( 
    485                new_e, (OSError, NewConnectionError, TimeoutError, SSLError) 
    486            ) and (conn and conn.proxy and not conn.has_connected_to_proxy): 
    487                new_e = _wrap_proxy_error(new_e, conn.proxy.scheme) 
    488            raise new_e 
    489 
    490        # conn.request() calls http.client.*.request, not the method in 
    491        # urllib3.request. It also calls makefile (recv) on the socket. 
    492        try: 
    493            conn.request( 
    494                method, 
    495                url, 
    496                body=body, 
    497                headers=headers, 
    498                chunked=chunked, 
    499                preload_content=preload_content, 
    500                decode_content=decode_content, 
    501                enforce_content_length=enforce_content_length, 
    502            ) 
    503 
    504        # We are swallowing BrokenPipeError (errno.EPIPE) since the server is 
    505        # legitimately able to close the connection after sending a valid response. 
    506        # With this behaviour, the received response is still readable. 
    507        except BrokenPipeError: 
    508            pass 
    509        except OSError as e: 
    510            # MacOS/Linux 
    511            # EPROTOTYPE and ECONNRESET are needed on macOS 
    512            # https://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/ 
    513            # Condition changed later to emit ECONNRESET instead of only EPROTOTYPE. 
    514            if e.errno != errno.EPROTOTYPE and e.errno != errno.ECONNRESET: 
    515                raise 
    516 
    517        # Reset the timeout for the recv() on the socket 
    518        read_timeout = timeout_obj.read_timeout 
    519 
    520        if not conn.is_closed: 
    521            # In Python 3 socket.py will catch EAGAIN and return None when you 
    522            # try and read into the file pointer created by http.client, which 
    523            # instead raises a BadStatusLine exception. Instead of catching 
    524            # the exception and assuming all BadStatusLine exceptions are read 
    525            # timeouts, check for a zero timeout before making the request. 
    526            if read_timeout == 0: 
    527                raise ReadTimeoutError( 
    528                    self, url, f"Read timed out. (read timeout={read_timeout})" 
    529                ) 
    530            conn.timeout = read_timeout 
    531 
    532        # Receive the response from the server 
    533        try: 
    534            response = conn.getresponse() 
    535        except (BaseSSLError, OSError) as e: 
    536            self._raise_timeout(err=e, url=url, timeout_value=read_timeout) 
    537            raise 
    538 
    539        # Set properties that are used by the pooling layer. 
    540        response.retries = retries 
    541        response._connection = response_conn  # type: ignore[attr-defined] 
    542        response._pool = self  # type: ignore[attr-defined] 
    543 
    544        log.debug( 
    545            '%s://%s:%s "%s %s %s" %s %s', 
    546            self.scheme, 
    547            self.host, 
    548            self.port, 
    549            method, 
    550            url, 
    551            response.version_string, 
    552            response.status, 
    553            response.length_remaining, 
    554        ) 
    555 
    556        return response 
    557 
    558    def close(self) -> None: 
    559        """ 
    560        Close all pooled connections and disable the pool. 
    561        """ 
    562        if self.pool is None: 
    563            return 
    564        # Disable access to the pool 
    565        old_pool, self.pool = self.pool, None 
    566 
    567        # Close all the HTTPConnections in the pool. 
    568        _close_pool_connections(old_pool) 
    569 
    570    def is_same_host(self, url: str) -> bool: 
    571        """ 
    572        Check if the given ``url`` is a member of the same host as this 
    573        connection pool. 
    574        """ 
    575        if url.startswith("/"): 
    576            return True 
    577 
    578        # TODO: Add optional support for socket.gethostbyname checking. 
    579        scheme, _, host, port, *_ = parse_url(url) 
    580        scheme = scheme or "http" 
    581        if host is not None: 
    582            host = _normalize_host(host, scheme=scheme) 
    583 
    584        # Use explicit default port for comparison when none is given 
    585        if self.port and not port: 
    586            port = port_by_scheme.get(scheme) 
    587        elif not self.port and port == port_by_scheme.get(scheme): 
    588            port = None 
    589 
    590        return (scheme, host, port) == (self.scheme, self.host, self.port) 
    591 
    592    def urlopen(  # type: ignore[override] 
    593        self, 
    594        method: str, 
    595        url: str, 
    596        body: _TYPE_BODY | None = None, 
    597        headers: typing.Mapping[str, str] | None = None, 
    598        retries: Retry | bool | int | None = None, 
    599        redirect: bool = True, 
    600        assert_same_host: bool = True, 
    601        timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, 
    602        pool_timeout: int | None = None, 
    603        release_conn: bool | None = None, 
    604        chunked: bool = False, 
    605        body_pos: _TYPE_BODY_POSITION | None = None, 
    606        preload_content: bool = True, 
    607        decode_content: bool = True, 
    608        **response_kw: typing.Any, 
    609    ) -> BaseHTTPResponse: 
    610        """ 
    611        Get a connection from the pool and perform an HTTP request. This is the 
    612        lowest level call for making a request, so you'll need to specify all 
    613        the raw details. 
    614 
    615        .. note:: 
    616 
    617           More commonly, it's appropriate to use a convenience method 
    618           such as :meth:`request`. 
    619 
    620        .. note:: 
    621 
    622           `release_conn` will only behave as expected if 
    623           `preload_content=False` because we want to make 
    624           `preload_content=False` the default behaviour someday soon without 
    625           breaking backwards compatibility. 
    626 
    627        :param method: 
    628            HTTP request method (such as GET, POST, PUT, etc.) 
    629 
    630        :param url: 
    631            The URL to perform the request on. 
    632 
    633        :param body: 
    634            Data to send in the request body, either :class:`str`, :class:`bytes`, 
    635            an iterable of :class:`str`/:class:`bytes`, or a file-like object. 
    636 
    637        :param headers: 
    638            Dictionary of custom headers to send, such as User-Agent, 
    639            If-None-Match, etc. If None, pool headers are used. If provided, 
    640            these headers completely replace any pool-specific headers. 
    641 
    642        :param retries: 
    643            Configure the number of retries to allow before raising a 
    644            :class:`~urllib3.exceptions.MaxRetryError` exception. 
    645 
    646            If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a 
    647            :class:`~urllib3.util.retry.Retry` object for fine-grained control 
    648            over different types of retries. 
    649            Pass an integer number to retry connection errors that many times, 
    650            but no other types of errors. Pass zero to never retry. 
    651 
    652            If ``False``, then retries are disabled and any exception is raised 
    653            immediately. Also, instead of raising a MaxRetryError on redirects, 
    654            the redirect response will be returned. 
    655 
    656        :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. 
    657 
    658        :param redirect: 
    659            If True, automatically handle redirects (status codes 301, 302, 
    660            303, 307, 308). Each redirect counts as a retry. Disabling retries 
    661            will disable redirect, too. 
    662 
    663        :param assert_same_host: 
    664            If ``True``, will make sure that the host of the pool requests is 
    665            consistent else will raise HostChangedError. When ``False``, you can 
    666            use the pool on an HTTP proxy and request foreign hosts. 
    667 
    668        :param timeout: 
    669            If specified, overrides the default timeout for this one 
    670            request. It may be a float (in seconds) or an instance of 
    671            :class:`urllib3.util.Timeout`. 
    672 
    673        :param pool_timeout: 
    674            If set and the pool is set to block=True, then this method will 
    675            block for ``pool_timeout`` seconds and raise EmptyPoolError if no 
    676            connection is available within the time period. 
    677 
    678        :param bool preload_content: 
    679            If True, the response's body will be preloaded into memory. 
    680 
    681        :param bool decode_content: 
    682            If True, will attempt to decode the body based on the 
    683            'content-encoding' header. 
    684 
    685        :param release_conn: 
    686            If False, then the urlopen call will not release the connection 
    687            back into the pool once a response is received (but will release if 
    688            you read the entire contents of the response such as when 
    689            `preload_content=True`). This is useful if you're not preloading 
    690            the response's content immediately. You will need to call 
    691            ``r.release_conn()`` on the response ``r`` to return the connection 
    692            back into the pool. If None, it takes the value of ``preload_content`` 
    693            which defaults to ``True``. 
    694 
    695        :param bool chunked: 
    696            If True, urllib3 will send the body using chunked transfer 
    697            encoding. Otherwise, urllib3 will send the body using the standard 
    698            content-length form. Defaults to False. 
    699 
    700        :param int body_pos: 
    701            Position to seek to in file-like body in the event of a retry or 
    702            redirect. Typically this won't need to be set because urllib3 will 
    703            auto-populate the value when needed. 
    704        """ 
    705        parsed_url = parse_url(url) 
    706        destination_scheme = parsed_url.scheme 
    707 
    708        if headers is None: 
    709            headers = self.headers 
    710 
    711        if not isinstance(retries, Retry): 
    712            retries = Retry.from_int(retries, redirect=redirect, default=self.retries) 
    713 
    714        if release_conn is None: 
    715            release_conn = preload_content 
    716 
    717        # Check host 
    718        if assert_same_host and not self.is_same_host(url): 
    719            raise HostChangedError(self, url, retries) 
    720 
    721        # Ensure that the URL we're connecting to is properly encoded 
    722        if url.startswith("/"): 
    723            url = to_str(_encode_target(url)) 
    724        else: 
    725            url = to_str(parsed_url.url) 
    726 
    727        conn = None 
    728 
    729        # Track whether `conn` needs to be released before 
    730        # returning/raising/recursing. Update this variable if necessary, and 
    731        # leave `release_conn` constant throughout the function. That way, if 
    732        # the function recurses, the original value of `release_conn` will be 
    733        # passed down into the recursive call, and its value will be respected. 
    734        # 
    735        # See issue #651 [1] for details. 
    736        # 
    737        # [1] <https://github.com/urllib3/urllib3/issues/651> 
    738        release_this_conn = release_conn 
    739 
    740        http_tunnel_required = connection_requires_http_tunnel( 
    741            self.proxy, self.proxy_config, destination_scheme 
    742        ) 
    743 
    744        # Merge the proxy headers. Only done when not using HTTP CONNECT. We 
    745        # have to copy the headers dict so we can safely change it without those 
    746        # changes being reflected in anyone else's copy. 
    747        if not http_tunnel_required: 
    748            headers = headers.copy()  # type: ignore[attr-defined] 
    749            headers.update(self.proxy_headers)  # type: ignore[union-attr] 
    750 
    751        # Must keep the exception bound to a separate variable or else Python 3 
    752        # complains about UnboundLocalError. 
    753        err = None 
    754 
    755        # Keep track of whether we cleanly exited the except block. This 
    756        # ensures we do proper cleanup in finally. 
    757        clean_exit = False 
    758 
    759        # Rewind body position, if needed. Record current position 
    760        # for future rewinds in the event of a redirect/retry. 
    761        body_pos = set_file_position(body, body_pos) 
    762 
    763        try: 
    764            # Request a connection from the queue. 
    765            timeout_obj = self._get_timeout(timeout) 
    766            conn = self._get_conn(timeout=pool_timeout) 
    767 
    768            conn.timeout = timeout_obj.connect_timeout  # type: ignore[assignment] 
    769 
    770            # Is this a closed/new connection that requires CONNECT tunnelling? 
    771            if self.proxy is not None and http_tunnel_required and conn.is_closed: 
    772                try: 
    773                    self._prepare_proxy(conn) 
    774                except (BaseSSLError, OSError, SocketTimeout) as e: 
    775                    self._raise_timeout( 
    776                        err=e, url=self.proxy.url, timeout_value=conn.timeout 
    777                    ) 
    778                    raise 
    779 
    780            # If we're going to release the connection in ``finally:``, then 
    781            # the response doesn't need to know about the connection. Otherwise 
    782            # it will also try to release it and we'll have a double-release 
    783            # mess. 
    784            response_conn = conn if not release_conn else None 
    785 
    786            # Make the request on the HTTPConnection object 
    787            response = self._make_request( 
    788                conn, 
    789                method, 
    790                url, 
    791                timeout=timeout_obj, 
    792                body=body, 
    793                headers=headers, 
    794                chunked=chunked, 
    795                retries=retries, 
    796                response_conn=response_conn, 
    797                preload_content=preload_content, 
    798                decode_content=decode_content, 
    799                **response_kw, 
    800            ) 
    801 
    802            # Everything went great! 
    803            clean_exit = True 
    804 
    805        except EmptyPoolError: 
    806            # Didn't get a connection from the pool, no need to clean up 
    807            clean_exit = True 
    808            release_this_conn = False 
    809            raise 
    810 
    811        except ( 
    812            TimeoutError, 
    813            HTTPException, 
    814            OSError, 
    815            ProtocolError, 
    816            BaseSSLError, 
    817            SSLError, 
    818            CertificateError, 
    819            ProxyError, 
    820        ) as e: 
    821            # Discard the connection for these exceptions. It will be 
    822            # replaced during the next _get_conn() call. 
    823            clean_exit = False 
    824            new_e: Exception = e 
    825            if isinstance(e, (BaseSSLError, CertificateError)): 
    826                new_e = SSLError(e) 
    827            if isinstance( 
    828                new_e, 
    829                ( 
    830                    OSError, 
    831                    NewConnectionError, 
    832                    TimeoutError, 
    833                    SSLError, 
    834                    HTTPException, 
    835                ), 
    836            ) and (conn and conn.proxy and not conn.has_connected_to_proxy): 
    837                new_e = _wrap_proxy_error(new_e, conn.proxy.scheme) 
    838            elif isinstance(new_e, (OSError, HTTPException)): 
    839                new_e = ProtocolError("Connection aborted.", new_e) 
    840 
    841            retries = retries.increment( 
    842                method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2] 
    843            ) 
    844            retries.sleep() 
    845 
    846            # Keep track of the error for the retry warning. 
    847            err = e 
    848 
    849        finally: 
    850            if not clean_exit: 
    851                # We hit some kind of exception, handled or otherwise. We need 
    852                # to throw the connection away unless explicitly told not to. 
    853                # Close the connection, set the variable to None, and make sure 
    854                # we put the None back in the pool to avoid leaking it. 
    855                if conn: 
    856                    conn.close() 
    857                    conn = None 
    858                release_this_conn = True 
    859 
    860            if release_this_conn: 
    861                # Put the connection back to be reused. If the connection is 
    862                # expired then it will be None, which will get replaced with a 
    863                # fresh connection during _get_conn. 
    864                self._put_conn(conn) 
    865 
    866        if not conn: 
    867            # Try again 
    868            log.warning( 
    869                "Retrying (%r) after connection broken by '%r': %s", retries, err, url 
    870            ) 
    871            return self.urlopen( 
    872                method, 
    873                url, 
    874                body, 
    875                headers, 
    876                retries, 
    877                redirect, 
    878                assert_same_host, 
    879                timeout=timeout, 
    880                pool_timeout=pool_timeout, 
    881                release_conn=release_conn, 
    882                chunked=chunked, 
    883                body_pos=body_pos, 
    884                preload_content=preload_content, 
    885                decode_content=decode_content, 
    886                **response_kw, 
    887            ) 
    888 
    889        # Handle redirect? 
    890        redirect_location = redirect and response.get_redirect_location() 
    891        if redirect_location: 
    892            if response.status == 303: 
    893                # Change the method according to RFC 9110, Section 15.4.4. 
    894                method = "GET" 
    895                # And lose the body not to transfer anything sensitive. 
    896                body = None 
    897                headers = HTTPHeaderDict(headers)._prepare_for_method_change() 
    898 
    899            try: 
    900                retries = retries.increment(method, url, response=response, _pool=self) 
    901            except MaxRetryError: 
    902                if retries.raise_on_redirect: 
    903                    response.drain_conn() 
    904                    raise 
    905                return response 
    906 
    907            response.drain_conn() 
    908            retries.sleep_for_retry(response) 
    909            log.debug("Redirecting %s -> %s", url, redirect_location) 
    910            return self.urlopen( 
    911                method, 
    912                redirect_location, 
    913                body, 
    914                headers, 
    915                retries=retries, 
    916                redirect=redirect, 
    917                assert_same_host=assert_same_host, 
    918                timeout=timeout, 
    919                pool_timeout=pool_timeout, 
    920                release_conn=release_conn, 
    921                chunked=chunked, 
    922                body_pos=body_pos, 
    923                preload_content=preload_content, 
    924                decode_content=decode_content, 
    925                **response_kw, 
    926            ) 
    927 
    928        # Check if we should retry the HTTP response. 
    929        has_retry_after = bool(response.headers.get("Retry-After")) 
    930        if retries.is_retry(method, response.status, has_retry_after): 
    931            try: 
    932                retries = retries.increment(method, url, response=response, _pool=self) 
    933            except MaxRetryError: 
    934                if retries.raise_on_status: 
    935                    response.drain_conn() 
    936                    raise 
    937                return response 
    938 
    939            response.drain_conn() 
    940            retries.sleep(response) 
    941            log.debug("Retry: %s", url) 
    942            return self.urlopen( 
    943                method, 
    944                url, 
    945                body, 
    946                headers, 
    947                retries=retries, 
    948                redirect=redirect, 
    949                assert_same_host=assert_same_host, 
    950                timeout=timeout, 
    951                pool_timeout=pool_timeout, 
    952                release_conn=release_conn, 
    953                chunked=chunked, 
    954                body_pos=body_pos, 
    955                preload_content=preload_content, 
    956                decode_content=decode_content, 
    957                **response_kw, 
    958            ) 
    959 
    960        return response 
    961 
    962 
    963class HTTPSConnectionPool(HTTPConnectionPool): 
    964    """ 
    965    Same as :class:`.HTTPConnectionPool`, but HTTPS. 
    966 
    967    :class:`.HTTPSConnection` uses one of ``assert_fingerprint``, 
    968    ``assert_hostname`` and ``host`` in this order to verify connections. 
    969    If ``assert_hostname`` is False, no verification is done. 
    970 
    971    The ``key_file``, ``cert_file``, ``cert_reqs``, ``ca_certs``, 
    972    ``ca_cert_dir``, ``ssl_version``, ``key_password`` are only used if :mod:`ssl` 
    973    is available and are fed into :meth:`urllib3.util.ssl_wrap_socket` to upgrade 
    974    the connection socket into an SSL socket. 
    975    """ 
    976 
    977    scheme = "https" 
    978    ConnectionCls: type[BaseHTTPSConnection] = HTTPSConnection 
    979 
    980    def __init__( 
    981        self, 
    982        host: str, 
    983        port: int | None = None, 
    984        timeout: _TYPE_TIMEOUT | None = _DEFAULT_TIMEOUT, 
    985        maxsize: int = 1, 
    986        block: bool = False, 
    987        headers: typing.Mapping[str, str] | None = None, 
    988        retries: Retry | bool | int | None = None, 
    989        _proxy: Url | None = None, 
    990        _proxy_headers: typing.Mapping[str, str] | None = None, 
    991        key_file: str | None = None, 
    992        cert_file: str | None = None, 
    993        cert_reqs: int | str | None = None, 
    994        key_password: str | None = None, 
    995        ca_certs: str | None = None, 
    996        ssl_version: int | str | None = None, 
    997        ssl_minimum_version: ssl.TLSVersion | None = None, 
    998        ssl_maximum_version: ssl.TLSVersion | None = None, 
    999        assert_hostname: str | typing.Literal[False] | None = None, 
    1000        assert_fingerprint: str | None = None, 
    1001        ca_cert_dir: str | None = None, 
    1002        **conn_kw: typing.Any, 
    1003    ) -> None: 
    1004        super().__init__( 
    1005            host, 
    1006            port, 
    1007            timeout, 
    1008            maxsize, 
    1009            block, 
    1010            headers, 
    1011            retries, 
    1012            _proxy, 
    1013            _proxy_headers, 
    1014            **conn_kw, 
    1015        ) 
    1016 
    1017        self.key_file = key_file 
    1018        self.cert_file = cert_file 
    1019        self.cert_reqs = cert_reqs 
    1020        self.key_password = key_password 
    1021        self.ca_certs = ca_certs 
    1022        self.ca_cert_dir = ca_cert_dir 
    1023        self.ssl_version = ssl_version 
    1024        self.ssl_minimum_version = ssl_minimum_version 
    1025        self.ssl_maximum_version = ssl_maximum_version 
    1026        self.assert_hostname = assert_hostname 
    1027        self.assert_fingerprint = assert_fingerprint 
    1028 
    1029    def _prepare_proxy(self, conn: HTTPSConnection) -> None:  # type: ignore[override] 
    1030        """Establishes a tunnel connection through HTTP CONNECT.""" 
    1031        if self.proxy and self.proxy.scheme == "https": 
    1032            tunnel_scheme = "https" 
    1033        else: 
    1034            tunnel_scheme = "http" 
    1035 
    1036        conn.set_tunnel( 
    1037            scheme=tunnel_scheme, 
    1038            host=self._tunnel_host, 
    1039            port=self.port, 
    1040            headers=self.proxy_headers, 
    1041        ) 
    1042        conn.connect() 
    1043 
    1044    def _new_conn(self) -> BaseHTTPSConnection: 
    1045        """ 
    1046        Return a fresh :class:`urllib3.connection.HTTPConnection`. 
    1047        """ 
    1048        self.num_connections += 1 
    1049        log.debug( 
    1050            "Starting new HTTPS connection (%d): %s:%s", 
    1051            self.num_connections, 
    1052            self.host, 
    1053            self.port or "443", 
    1054        ) 
    1055 
    1056        if not self.ConnectionCls or self.ConnectionCls is DummyConnection:  # type: ignore[comparison-overlap] 
    1057            raise ImportError( 
    1058                "Can't connect to HTTPS URL because the SSL module is not available." 
    1059            ) 
    1060 
    1061        actual_host: str = self.host 
    1062        actual_port = self.port 
    1063        if self.proxy is not None and self.proxy.host is not None: 
    1064            actual_host = self.proxy.host 
    1065            actual_port = self.proxy.port 
    1066 
    1067        return self.ConnectionCls( 
    1068            host=actual_host, 
    1069            port=actual_port, 
    1070            timeout=self.timeout.connect_timeout, 
    1071            cert_file=self.cert_file, 
    1072            key_file=self.key_file, 
    1073            key_password=self.key_password, 
    1074            cert_reqs=self.cert_reqs, 
    1075            ca_certs=self.ca_certs, 
    1076            ca_cert_dir=self.ca_cert_dir, 
    1077            assert_hostname=self.assert_hostname, 
    1078            assert_fingerprint=self.assert_fingerprint, 
    1079            ssl_version=self.ssl_version, 
    1080            ssl_minimum_version=self.ssl_minimum_version, 
    1081            ssl_maximum_version=self.ssl_maximum_version, 
    1082            **self.conn_kw, 
    1083        ) 
    1084 
    1085    def _validate_conn(self, conn: BaseHTTPConnection) -> None: 
    1086        """ 
    1087        Called right before a request is made, after the socket is created. 
    1088        """ 
    1089        super()._validate_conn(conn) 
    1090 
    1091        # Force connect early to allow us to validate the connection. 
    1092        if conn.is_closed: 
    1093            conn.connect() 
    1094 
    1095        # TODO revise this, see https://github.com/urllib3/urllib3/issues/2791 
    1096        if not conn.is_verified and not conn.proxy_is_verified: 
    1097            warnings.warn( 
    1098                ( 
    1099                    f"Unverified HTTPS request is being made to host '{conn.host}'. " 
    1100                    "Adding certificate verification is strongly advised. See: " 
    1101                    "https://urllib3.readthedocs.io/en/latest/advanced-usage.html" 
    1102                    "#tls-warnings" 
    1103                ), 
    1104                InsecureRequestWarning, 
    1105            ) 
    1106 
    1107 
    1108def connection_from_url(url: str, **kw: typing.Any) -> HTTPConnectionPool: 
    1109    """ 
    1110    Given a url, return an :class:`.ConnectionPool` instance of its host. 
    1111 
    1112    This is a shortcut for not having to parse out the scheme, host, and port 
    1113    of the url before creating an :class:`.ConnectionPool` instance. 
    1114 
    1115    :param url: 
    1116        Absolute URL string that must include the scheme. Port is optional. 
    1117 
    1118    :param \\**kw: 
    1119        Passes additional parameters to the constructor of the appropriate 
    1120        :class:`.ConnectionPool`. Useful for specifying things like 
    1121        timeout, maxsize, headers, etc. 
    1122 
    1123    Example:: 
    1124 
    1125        >>> conn = connection_from_url('http://google.com/') 
    1126        >>> r = conn.request('GET', '/') 
    1127    """ 
    1128    scheme, _, host, port, *_ = parse_url(url) 
    1129    scheme = scheme or "http" 
    1130    port = port or port_by_scheme.get(scheme, 80) 
    1131    if scheme == "https": 
    1132        return HTTPSConnectionPool(host, port=port, **kw)  # type: ignore[arg-type] 
    1133    else: 
    1134        return HTTPConnectionPool(host, port=port, **kw)  # type: ignore[arg-type] 
    1135 
    1136 
    1137@typing.overload 
    1138def _normalize_host(host: None, scheme: str | None) -> None: ... 
    1139 
    1140 
    1141@typing.overload 
    1142def _normalize_host(host: str, scheme: str | None) -> str: ... 
    1143 
    1144 
    1145def _normalize_host(host: str | None, scheme: str | None) -> str | None: 
    1146    """ 
    1147    Normalize hosts for comparisons and use with sockets. 
    1148    """ 
    1149 
    1150    host = normalize_host(host, scheme) 
    1151 
    1152    # httplib doesn't like it when we include brackets in IPv6 addresses 
    1153    # Specifically, if we include brackets but also pass the port then 
    1154    # httplib crazily doubles up the square brackets on the Host header. 
    1155    # Instead, we need to make sure we never pass ``None`` as the port. 
    1156    # However, for backward compatibility reasons we can't actually 
    1157    # *assert* that.  See http://bugs.python.org/issue28539 
    1158    if host and host.startswith("[") and host.endswith("]"): 
    1159        host = host[1:-1] 
    1160    return host 
    1161 
    1162 
    1163def _url_from_pool( 
    1164    pool: HTTPConnectionPool | HTTPSConnectionPool, path: str | None = None 
    1165) -> str: 
    1166    """Returns the URL from a given connection pool. This is mainly used for testing and logging.""" 
    1167    return Url(scheme=pool.scheme, host=pool.host, port=pool.port, path=path).url 
    1168 
    1169 
    1170def _close_pool_connections(pool: queue.LifoQueue[typing.Any]) -> None: 
    1171    """Drains a queue of connections and closes each one.""" 
    1172    try: 
    1173        while True: 
    1174            conn = pool.get(block=False) 
    1175            if conn: 
    1176                conn.close() 
    1177    except queue.Empty: 
    1178        pass  # Done.