@@ -5033,7 +5033,7 @@ async def final_handler(request: web.Request) -> web.Response:
50335033
50345034
50355035async def test_async_iterable_payload_redirect (aiohttp_client : AiohttpClient ) -> None :
5036- """Test that AsyncIterablePayload cannot be reused across redirects ."""
5036+ """Test redirecting consumed AsyncIterablePayload raises an error ."""
50375037 data_received = []
50385038
50395039 async def redirect_handler (request : web .Request ) -> web .Response :
@@ -5061,17 +5061,50 @@ async def async_gen() -> AsyncIterator[bytes]:
50615061
50625062 payload = AsyncIterablePayload (async_gen ())
50635063
5064- resp = await client .post ("/redirect" , data = payload )
5065- assert resp .status == 200
5066- text = await resp .text ()
5067- # AsyncIterablePayload is consumed after first use, so redirect gets empty body
5068- assert text == "Received: "
5064+ with pytest .raises (
5065+ aiohttp .ClientPayloadError ,
5066+ match = "Cannot follow redirect with a consumed request body" ,
5067+ ):
5068+ await client .post ("/redirect" , data = payload )
5069+
5070+ # Only the first endpoint should have received data.
5071+ expected_data = b"" .join (chunks )
5072+ assert data_received == [("redirect" , expected_data )]
5073+
5074+
5075+ @pytest .mark .parametrize ("status" , (301 , 302 ))
5076+ async def test_async_iterable_payload_redirect_non_post_301_302 (
5077+ aiohttp_client : AiohttpClient , status : int
5078+ ) -> None :
5079+ """Test consumed async iterable body raises on 301/302 for non-POST methods."""
5080+ data_received = []
5081+
5082+ async def redirect_handler (request : web .Request ) -> web .Response :
5083+ data = await request .read ()
5084+ data_received .append (("redirect" , data ))
5085+ return web .Response (status = status , headers = {"Location" : "/final_destination" })
5086+
5087+ app = web .Application ()
5088+ app .router .add_put ("/redirect" , redirect_handler )
5089+
5090+ client = await aiohttp_client (app )
5091+
5092+ chunks = [b"chunk1" , b"chunk2" , b"chunk3" ]
5093+
5094+ async def async_gen () -> AsyncIterator [bytes ]:
5095+ for chunk in chunks :
5096+ yield chunk
5097+
5098+ payload = AsyncIterablePayload (async_gen ())
5099+
5100+ with pytest .raises (
5101+ aiohttp .ClientPayloadError ,
5102+ match = "Cannot follow redirect with a consumed request body" ,
5103+ ):
5104+ await client .put ("/redirect" , data = payload )
50695105
5070- # Only the first endpoint should have received data
50715106 expected_data = b"" .join (chunks )
5072- assert len (data_received ) == 2
5073- assert data_received [0 ] == ("redirect" , expected_data )
5074- assert data_received [1 ] == ("final" , b"" ) # Empty after being consumed
5107+ assert data_received == [("redirect" , expected_data )]
50755108
50765109
50775110async def test_buffered_reader_payload_redirect (aiohttp_client : AiohttpClient ) -> None :
0 commit comments