Skip to content

Incorrect reuse of FormData on certain redirects #5577

@jesseanttila-cai

Description

@jesseanttila-cai

🐞 Describe the bug

If a POST request results in a redirect response with response code 307 or 308, aiohttp.client may attempt to construct another POST request with the redirected URL using the same data as the first request. If the value passed as the data argument is an instance of aiohttp.FormData, this will fail with a somewhat cryptic exception: "RuntimeError: Form data has been processed already".

💡 To Reproduce

  1. Send a POST request with FormData to a server that will respond with code 307 or 308

💡 Expected behavior

Instead of reconstructing the body for each request, perhaps the request body could be reused. This would also resolve #5530, which appears to have a similar root cause.

📋 Logs/tracebacks

  File "--", line --, in --
    async with session.post(url, data=data) as response:
  File "/usr/local/lib/python3.8/dist-packages/aiohttp/client.py", line 1118, in __aenter__
    self._resp = await self._coro
  File "/usr/local/lib/python3.8/dist-packages/aiohttp/client.py", line 493, in _request
    req = self._request_class(
  File "/usr/local/lib/python3.8/dist-packages/aiohttp/client_reqrep.py", line 313, in __init__
    self.update_body_from_data(data)
  File "/usr/local/lib/python3.8/dist-packages/aiohttp/client_reqrep.py", line 507, in update_body_from_data
    body = body()
  File "/usr/local/lib/python3.8/dist-packages/aiohttp/formdata.py", line 169, in __call__
    return self._gen_form_data()
  File "/usr/local/lib/python3.8/dist-packages/aiohttp/formdata.py", line 133, in _gen_form_data
    raise RuntimeError("Form data has been processed already")
RuntimeError: Form data has been processed already

📋 Your version of the Python

$ python --version
Python 3.8.5

📋 Your version of the aiohttp/yarl/multidict distributions

$ python -m pip show aiohttp
Name: aiohttp
Version: 3.7.4.post0
Summary: Async http client/server framework (asyncio)
Home-page: https://github.com/aio-libs/aiohttp
Author: Nikolay Kim
Author-email: [email protected]
License: Apache 2
Location: /usr/local/lib/python3.8/dist-packages
Requires: attrs, chardet, yarl, multidict, typing-extensions, async-timeout
$ python -m pip show multidict
Version: 5.1.0
Summary: multidict implementation
Home-page: https://github.com/aio-libs/multidict
Author: Andrew Svetlov
Author-email: [email protected]
License: Apache 2
Location: /usr/local/lib/python3.8/dist-packages
Requires: 
Required-by: yarl, aiohttp
$ python -m pip show yarl
Name: yarl
Version: 1.6.3
Summary: Yet another URL library
Home-page: https://github.com/aio-libs/yarl/
Author: Andrew Svetlov
Author-email: [email protected]
License: Apache 2
Location: /usr/local/lib/python3.8/dist-packages
Requires: idna, multidict
Required-by: aiohttp

📋 Additional context

This is a client issue.

For anyone else who has encountered this issue: Skipping the redirect by sending the original request to the redirected URL may be an adequate workaround at least in the case of a permanent redirect.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions