Skip to content

Cannot access an error message when receive 400 #4600

Description

@yeralin

🐞 Describe the bug
While using aiohttp.client.ClientSession to send requests and receive responses, I found out that I cannot access a bad response's error message while catching ClientResponseError because aiohttp simply does not propagate the response content when raising ClientResponseError here:

def raise_for_status(self) -> None:
if 400 <= self.status:
# reason should always be not None for a started response
assert self.reason is not None
self.release()
raise ClientResponseError(
self.request_info,
self.history,
status=self.status,
message=self.reason,
headers=self.headers)

It only passes self.status == 400 and self.reason == "BAD REQUEST".

💡 To Reproduce

from aiohttp import ClientResponseError, ClientSession

session = ClientSession(raise_for_status=True)

try:
    # assuming that the request will result in 400 BAD REQUEST with a specific error message
    async with session.post(**kwargs) as response: 
        # handle response
except ClientResponseError as ex:
    print(ex.__dict__) 
    """
        {'request_info': RequestInfo(...), 
        'status': 400, 
        'message': 'BAD REQUEST', 
        'headers': ..., 
        'history': ()}
    """

💡 Expected behavior
Received ClientResponseError should contain a response message received along with 400 response.

📋 Logs/tracebacks

Not applicable

📋 Your version of the Python

$ python --version
Python 3.7.6

📋 Your version of the aiohttp/yarl/multidict distributions

$ python -m pip show aiohttp
Name: aiohttp
Version: 3.5.4
Summary: Async http client/server framework (asyncio)
Home-page: https://github.com/aio-libs/aiohttp
Author: Nikolay Kim
Author-email: fafhrd91@gmail.com
License: Apache 2
Location: /Applications/miniconda3/envs/sw-asyncher-services/lib/python3.7/site-packages
Requires: yarl, async-timeout, attrs, multidict, chardet
Required-by: aiojobs, aiohttp-apispec
$ python -m pip show multidict
Name: multidict
Version: 4.7.5
Summary: multidict implementation
Home-page: https://github.com/aio-libs/multidict
Author: Andrew Svetlov
Author-email: andrew.svetlov@gmail.com
License: Apache 2
Location: /Applications/miniconda3/envs/sw-asyncher-services/lib/python3.7/site-packages
Requires:
Required-by: yarl, aiohttp
$ python -m pip show yarl
Name: yarl
Version: 1.4.2
Summary: Yet another URL library
Home-page: https://github.com/aio-libs/yarl/
Author: Andrew Svetlov
Author-email: andrew.svetlov@gmail.com
License: Apache 2
Location: /Applications/miniconda3/envs/sw-asyncher-services/lib/python3.7/site-packages
Requires: idna, multidict
Required-by: aiohttp

📋 Additional context
On the server side, when I change the response from 400 to any non-bad response say 200, I can access passed error message.

Current workaround would be to have session = ClientSession(raise_for_status=False), and handle bad responses manually.

🔷 Possible solution
Modify ClientResponseError exception to include an error message, convert raise_for_status method to be async to be able to read the response message, and raise ClientResponseError with the read message.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions