diff --git a/CHANGES.rst b/CHANGES.rst index 14c5b5b08ad..3dfa448a54a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,6 +10,65 @@ .. towncrier release notes start +3.12.14 (2025-07-10) +==================== + +Bug fixes +--------- + +- Fixed file uploads failing with HTTP 422 errors when encountering 307/308 redirects, and 301/302 redirects for non-POST methods, by preserving the request body when appropriate per :rfc:`9110#section-15.4.3-3.1` -- by :user:`bdraco`. + + + *Related issues and pull requests on GitHub:* + :issue:`11270`. + + + +- Fixed :py:meth:`ClientSession.close() ` hanging indefinitely when using HTTPS requests through HTTP proxies -- by :user:`bdraco`. + + + *Related issues and pull requests on GitHub:* + :issue:`11273`. + + + +- Bumped minimum version of aiosignal to 1.4+ to resolve typing issues -- by :user:`Dreamsorcerer`. + + + *Related issues and pull requests on GitHub:* + :issue:`11280`. + + + + +Features +-------- + +- Added initial trailer parsing logic to Python HTTP parser -- by :user:`Dreamsorcerer`. + + + *Related issues and pull requests on GitHub:* + :issue:`11269`. + + + + +Improved documentation +---------------------- + +- Clarified exceptions raised by ``WebSocketResponse.send_frame`` et al. + -- by :user:`DoctorJohn`. + + + *Related issues and pull requests on GitHub:* + :issue:`11234`. + + + + +---- + + 3.12.13 (2025-06-14) ==================== diff --git a/CHANGES/11234.doc.rst b/CHANGES/11234.doc.rst deleted file mode 100644 index 900b56a771c..00000000000 --- a/CHANGES/11234.doc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Clarified exceptions raised by ``WebSocketResponse.send_frame`` at al. --- by :user:`DoctorJohn`. diff --git a/CHANGES/11269.feature.rst b/CHANGES/11269.feature.rst deleted file mode 100644 index 92cf173be14..00000000000 --- a/CHANGES/11269.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Added initial trailer parsing logic to Python HTTP parser -- by :user:`Dreamsorcerer`. diff --git a/CHANGES/11270.bugfix.rst b/CHANGES/11270.bugfix.rst deleted file mode 100644 index d1e0992b949..00000000000 --- a/CHANGES/11270.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed file uploads failing with HTTP 422 errors when encountering 307/308 redirects, and 301/302 redirects for non-POST methods, by preserving the request body when appropriate per :rfc:`9110#section-15.4.3-3.1` -- by :user:`bdraco`. diff --git a/CHANGES/11273.bugfix.rst b/CHANGES/11273.bugfix.rst deleted file mode 100644 index b4d9948fbcd..00000000000 --- a/CHANGES/11273.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed :py:meth:`ClientSession.close() ` hanging indefinitely when using HTTPS requests through HTTP proxies -- by :user:`bdraco`. diff --git a/CHANGES/11280.misc.rst b/CHANGES/11280.misc.rst deleted file mode 100644 index 6750918bda7..00000000000 --- a/CHANGES/11280.misc.rst +++ /dev/null @@ -1 +0,0 @@ -Bumped minimum version of aiosignal to 1.4+ to resolve typing issues -- by :user:`Dreamsorcerer`. diff --git a/tests/test_client_functional.py b/tests/test_client_functional.py index 23ace2f6d4e..d403aab107e 100644 --- a/tests/test_client_functional.py +++ b/tests/test_client_functional.py @@ -5368,7 +5368,7 @@ async def test_file_upload_307_308_redirect( This demonstrates the bug where file payloads get incorrect Content-Length on redirect because the file position isn't reset. """ - received_bodies: List[bytes] = [] + received_bodies: list[bytes] = [] async def handler(request: web.Request) -> web.Response: # Store the body content @@ -5432,7 +5432,7 @@ async def test_file_upload_301_302_redirect_non_post( Per RFC 9110, 301/302 redirects should preserve the method and body for non-POST requests. """ - received_bodies: List[bytes] = [] + received_bodies: list[bytes] = [] async def handler(request: web.Request) -> web.Response: # Store the body content @@ -5499,7 +5499,7 @@ async def test_file_upload_307_302_redirect_chain( 2. 302 changes POST to GET and drops the body 3. No body leaks to the final GET request """ - received_requests: List[Dict[str, Any]] = [] + received_requests: list[dict[str, Any]] = [] async def handler(request: web.Request) -> web.Response: # Store request details diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py index 38c6971b037..69e1fd7d4cc 100644 --- a/tests/test_http_parser.py +++ b/tests/test_http_parser.py @@ -1344,7 +1344,7 @@ async def test_request_chunked_reject_bad_trailer(parser: HttpRequestParser) -> def test_parse_no_length_or_te_on_post( loop: asyncio.AbstractEventLoop, protocol: BaseProtocol, - request_cls: Type[HttpRequestParser], + request_cls: type[HttpRequestParser], ) -> None: parser = request_cls(protocol, loop, limit=2**16) text = b"POST /test HTTP/1.1\r\n\r\n"