From f28deff1cf162c673b50d88d3552e91bda6d68a8 Mon Sep 17 00:00:00 2001 From: Illia Volochii Date: Mon, 2 Oct 2023 22:17:55 +0300 Subject: [PATCH 1/4] Add 1.26.17 to the current changelog --- CHANGES.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index e551cbea40..27038fef47 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -167,6 +167,11 @@ Fixed * Fixed a socket leak if ``HTTPConnection.connect()`` fails (`#2571 `__). * Fixed ``urllib3.contrib.pyopenssl.WrappedSocket`` and ``urllib3.contrib.securetransport.WrappedSocket`` close methods (`#2970 `__) +1.26.17 (2023-10-02) +==================== + +* Added the ``Cookie`` header to the list of headers to strip from requests when redirecting to a different host. As before, different headers can be set via ``Retry.remove_headers_on_redirect``. (`#3139 `_) + 1.26.16 (2023-05-23) ==================== From 80808b04bfa68fbd099828848c96ee25df185f1d Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Fri, 6 Oct 2023 00:40:59 +0400 Subject: [PATCH 2/4] Fix docs build on Python 3.12 (#3144) --- src/urllib3/util/ssl_.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/urllib3/util/ssl_.py b/src/urllib3/util/ssl_.py index 7762803267..e35e394030 100644 --- a/src/urllib3/util/ssl_.py +++ b/src/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 From 4e50fbc5db74e32cabd5ccc1ab81fc103adfe0b3 Mon Sep 17 00:00:00 2001 From: Illia Volochii Date: Tue, 17 Oct 2023 19:35:39 +0300 Subject: [PATCH 3/4] Merge pull request from GHSA-g4mx-q9vg-27p4 --- dummyserver/handlers.py | 6 ++++++ src/urllib3/_collections.py | 20 +++++++++++++++++++- src/urllib3/connectionpool.py | 5 +++++ src/urllib3/poolmanager.py | 7 +++++-- test/with_dummyserver/test_connectionpool.py | 11 +++++++++++ test/with_dummyserver/test_poolmanager.py | 14 ++++++++++++++ 6 files changed, 60 insertions(+), 3 deletions(-) diff --git a/dummyserver/handlers.py b/dummyserver/handlers.py index 9fde80e041..86201a116f 100644 --- a/dummyserver/handlers.py +++ b/dummyserver/handlers.py @@ -281,6 +281,12 @@ def encodingrequest(self, request: httputil.HTTPServerRequest) -> Response: def headers(self, request: httputil.HTTPServerRequest) -> Response: return Response(json.dumps(dict(request.headers))) + def headers_and_params(self, request: httputil.HTTPServerRequest) -> Response: + params = request_params(request) + return Response( + json.dumps({"headers": dict(request.headers), "params": params}) + ) + def multi_headers(self, request: httputil.HTTPServerRequest) -> Response: return Response(json.dumps({"headers": list(request.headers.get_all())})) diff --git a/src/urllib3/_collections.py b/src/urllib3/_collections.py index 7f9dca7fa8..8bdfb767e6 100644 --- a/src/urllib3/_collections.py +++ b/src/urllib3/_collections.py @@ -8,7 +8,7 @@ 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 @@ def getlist( # 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/src/urllib3/connectionpool.py b/src/urllib3/connectionpool.py index 2479405bd5..c6ca390247 100644 --- a/src/urllib3/connectionpool.py +++ b/src/urllib3/connectionpool.py @@ -11,6 +11,7 @@ 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 @@ def urlopen( # type: ignore[override] 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/src/urllib3/poolmanager.py b/src/urllib3/poolmanager.py index 02b2f622a1..3c92a14deb 100644 --- a/src/urllib3/poolmanager.py +++ b/src/urllib3/poolmanager.py @@ -7,7 +7,7 @@ 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 @@ def urlopen( # type: ignore[override] # 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/test/with_dummyserver/test_connectionpool.py b/test/with_dummyserver/test_connectionpool.py index fdfb2c9aba..ebfaf3878f 100644 --- a/test/with_dummyserver/test_connectionpool.py +++ b/test/with_dummyserver/test_connectionpool.py @@ -480,6 +480,17 @@ def test_redirect(self) -> None: assert r.status == 200 assert r.data == b"Dummy server!" + def test_303_redirect_makes_request_lose_body(self) -> None: + with HTTPConnectionPool(self.host, self.port) as pool: + response = pool.request( + "POST", + "/redirect", + fields={"target": "/headers_and_params", "status": "303 See Other"}, + ) + data = response.json() + assert data["params"] == {} + assert "Content-Type" not in HTTPHeaderDict(data["headers"]) + def test_bad_connect(self) -> None: with HTTPConnectionPool("badhost.invalid", self.port) as pool: with pytest.raises(MaxRetryError) as e: diff --git a/test/with_dummyserver/test_poolmanager.py b/test/with_dummyserver/test_poolmanager.py index da802a38b3..ab0111e45b 100644 --- a/test/with_dummyserver/test_poolmanager.py +++ b/test/with_dummyserver/test_poolmanager.py @@ -244,6 +244,20 @@ def test_redirect_without_preload_releases_connection(self) -> None: assert r._pool.num_connections == 1 assert len(http.pools) == 1 + def test_303_redirect_makes_request_lose_body(self) -> None: + with PoolManager() as http: + response = http.request( + "POST", + f"{self.base_url}/redirect", + fields={ + "target": f"{self.base_url}/headers_and_params", + "status": "303 See Other", + }, + ) + data = response.json() + assert data["params"] == {} + assert "Content-Type" not in HTTPHeaderDict(data["headers"]) + def test_unknown_scheme(self) -> None: with PoolManager() as http: unknown_scheme = "unknown" From 56f01e088dc006c03d4ee6ea9da4ab810f1ed700 Mon Sep 17 00:00:00 2001 From: Illia Volochii Date: Tue, 17 Oct 2023 20:26:50 +0300 Subject: [PATCH 4/4] Release 2.0.7 --- .readthedocs.yml | 2 +- CHANGES.rst | 10 ++++++++++ dev-requirements.txt | 2 +- src/urllib3/_version.py | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index 78bd2064f6..7c59df5b3a 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -3,7 +3,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3" + python: "3.11" python: install: diff --git a/CHANGES.rst b/CHANGES.rst index 27038fef47..6c37aeba10 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,8 @@ +2.0.7 (2023-10-17) +================== + +* Made body stripped from HTTP requests changing the request method to GET after HTTP 303 "See Other" redirect responses. + 2.0.6 (2023-10-02) ================== @@ -167,6 +172,11 @@ Fixed * Fixed a socket leak if ``HTTPConnection.connect()`` fails (`#2571 `__). * Fixed ``urllib3.contrib.pyopenssl.WrappedSocket`` and ``urllib3.contrib.securetransport.WrappedSocket`` close methods (`#2970 `__) +1.26.18 (2023-10-17) +==================== + +* Made body stripped from HTTP requests changing the request method to GET after HTTP 303 "See Other" redirect responses. + 1.26.17 (2023-10-02) ==================== diff --git a/dev-requirements.txt b/dev-requirements.txt index 70f5097338..8b3632c37f 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -10,4 +10,4 @@ cryptography==39.0.2;implementation_name=="pypy" and implementation_version<"7.3 cryptography==41.0.4;implementation_name!="pypy" or implementation_version>="7.3.10" backports.zoneinfo==0.2.1;python_version<"3.9" towncrier==23.6.0 -pytest-memray==1.4.0;python_version>="3.8" and python_version<"3.12" and sys_platform!="win32" and implementation_name=="cpython" +pytest-memray==1.4.0;python_version>="3.8" and python_version<"3.13" and sys_platform!="win32" and implementation_name=="cpython" diff --git a/src/urllib3/_version.py b/src/urllib3/_version.py index 2d0d430896..e2b88f1d68 100644 --- a/src/urllib3/_version.py +++ b/src/urllib3/_version.py @@ -1,4 +1,4 @@ # This file is protected via CODEOWNERS from __future__ import annotations -__version__ = "2.0.6" +__version__ = "2.0.7" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy