From 3c251294f2669d508e4b8e99d2ac2e41534c1aed Mon Sep 17 00:00:00 2001 From: JackDandy Date: Sat, 21 Oct 2023 11:39:09 +0100 Subject: [PATCH] =?UTF-8?q?Update=20urllib3=202.0.5=20(d9f85a7)=20?= =?UTF-8?q?=E2=86=92=202.0.7=20(56f01e0).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGES.md | 1 + lib/urllib3/_collections.py | 20 +++++++++++++++++++- lib/urllib3/_version.py | 2 +- lib/urllib3/connectionpool.py | 5 +++++ lib/urllib3/poolmanager.py | 7 +++++-- lib/urllib3/util/retry.py | 2 +- lib/urllib3/util/ssl_.py | 6 ++++-- 7 files changed, 36 insertions(+), 7 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0c511980..883451b4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ * Update Rarfile 4.1a1 (8a72967) to 4.1 (c9140d8) * Update soupsieve 2.4.1 (2e66beb) to 2.5.0 (dc71495) * Update thefuzz 0.19.0 (c2cd4f4) to 0.21.0 (0b49e4a) +* Update urllib3 2.0.5 (d9f85a7) to 2.0.7 (56f01e0) * Add support for Brotli compression diff --git a/lib/urllib3/_collections.py b/lib/urllib3/_collections.py index 7f9dca7f..8bdfb767 100644 --- a/lib/urllib3/_collections.py +++ b/lib/urllib3/_collections.py @@ -8,7 +8,7 @@ from threading import RLock if typing.TYPE_CHECKING: # We can only import Protocol if TYPE_CHECKING because it's a development # dependency, and is not available at runtime. - from typing_extensions import Protocol + from typing_extensions import Protocol, Self class HasGettableStringKeys(Protocol): def keys(self) -> typing.Iterator[str]: @@ -391,6 +391,24 @@ class HTTPHeaderDict(typing.MutableMapping[str, str]): # meets our external interface requirement of `Union[List[str], _DT]`. return vals[1:] + def _prepare_for_method_change(self) -> Self: + """ + Remove content-specific header fields before changing the request + method to GET or HEAD according to RFC 9110, Section 15.4. + """ + content_specific_headers = [ + "Content-Encoding", + "Content-Language", + "Content-Location", + "Content-Type", + "Content-Length", + "Digest", + "Last-Modified", + ] + for header in content_specific_headers: + self.discard(header) + return self + # Backwards compatibility for httplib getheaders = getlist getallmatchingheaders = getlist diff --git a/lib/urllib3/_version.py b/lib/urllib3/_version.py index c9641905..e2b88f1d 100644 --- a/lib/urllib3/_version.py +++ b/lib/urllib3/_version.py @@ -1,4 +1,4 @@ # This file is protected via CODEOWNERS from __future__ import annotations -__version__ = "2.0.5" +__version__ = "2.0.7" diff --git a/lib/urllib3/connectionpool.py b/lib/urllib3/connectionpool.py index 2479405b..c6ca3902 100644 --- a/lib/urllib3/connectionpool.py +++ b/lib/urllib3/connectionpool.py @@ -11,6 +11,7 @@ from socket import timeout as SocketTimeout from types import TracebackType from ._base_connection import _TYPE_BODY +from ._collections import HTTPHeaderDict from ._request_methods import RequestMethods from .connection import ( BaseSSLError, @@ -893,7 +894,11 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): redirect_location = redirect and response.get_redirect_location() if redirect_location: if response.status == 303: + # Change the method according to RFC 9110, Section 15.4.4. method = "GET" + # And lose the body not to transfer anything sensitive. + body = None + headers = HTTPHeaderDict(headers)._prepare_for_method_change() try: retries = retries.increment(method, url, response=response, _pool=self) diff --git a/lib/urllib3/poolmanager.py b/lib/urllib3/poolmanager.py index 02b2f622..3c92a14d 100644 --- a/lib/urllib3/poolmanager.py +++ b/lib/urllib3/poolmanager.py @@ -7,7 +7,7 @@ import warnings from types import TracebackType from urllib.parse import urljoin -from ._collections import RecentlyUsedContainer +from ._collections import HTTPHeaderDict, RecentlyUsedContainer from ._request_methods import RequestMethods from .connection import ProxyConfig from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, port_by_scheme @@ -449,9 +449,12 @@ class PoolManager(RequestMethods): # Support relative URLs for redirecting. redirect_location = urljoin(url, redirect_location) - # RFC 7231, Section 6.4.4 if response.status == 303: + # Change the method according to RFC 9110, Section 15.4.4. method = "GET" + # And lose the body not to transfer anything sensitive. + kw["body"] = None + kw["headers"] = HTTPHeaderDict(kw["headers"])._prepare_for_method_change() retries = kw.get("retries") if not isinstance(retries, Retry): diff --git a/lib/urllib3/util/retry.py b/lib/urllib3/util/retry.py index ea48afe3..7572bfd2 100644 --- a/lib/urllib3/util/retry.py +++ b/lib/urllib3/util/retry.py @@ -187,7 +187,7 @@ class Retry: RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503]) #: Default headers to be used for ``remove_headers_on_redirect`` - DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(["Authorization"]) + DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(["Cookie", "Authorization"]) #: Default maximum backoff time. DEFAULT_BACKOFF_MAX = 120 diff --git a/lib/urllib3/util/ssl_.py b/lib/urllib3/util/ssl_.py index 77628032..e35e3940 100644 --- a/lib/urllib3/util/ssl_.py +++ b/lib/urllib3/util/ssl_.py @@ -411,8 +411,10 @@ def ssl_wrap_socket( tls_in_tls: bool = False, ) -> ssl.SSLSocket | SSLTransportType: """ - All arguments except for server_hostname, ssl_context, and ca_cert_dir have - the same meaning as they do when using :func:`ssl.wrap_socket`. + All arguments except for server_hostname, ssl_context, tls_in_tls, ca_cert_data and + ca_cert_dir have the same meaning as they do when using + :func:`ssl.create_default_context`, :meth:`ssl.SSLContext.load_cert_chain`, + :meth:`ssl.SSLContext.set_ciphers` and :meth:`ssl.SSLContext.wrap_socket`. :param server_hostname: When SNI is supported, the expected hostname of the certificate