I'm using FastAPI
with aiohttp
, I built a singleton for a persistent session and I'm using it for opening the session at startup and closing it at shutdown.
Demand: The response
body is precious in case of a failure I must log it with the other details.
Because how raise_for_status
behave I had to write those ugly functions which handle each HTTP method, this is one of them:
async def post(self, url: str, json: dict, headers: dict) -> ClientResponse:
response = await self.session.post(url=url, json=json, headers=headers)
response_body = await response.text()
try:
response.raise_for_status()
except Exception:
logger.exception('Request failed',
extra={'url': url, 'json': json, 'headers': headers, 'body': response_body})
raise
return response
If I could count on raise_for_status
to return also the body (response.text()
),
I just could initiate the session ClientSession(raise_for_status=True)
and write a clean code:
response = await self.session.post(url=url, json=json, headers=headers)
Is there a way to force somehow raise_for_status
to return also the payload/body, maybe in the initialization of the ClientSession
?
Thanks for the help.
It is not possible for aiohttp
and raise_for_status
. As @Andrew Svetlov answered here:
Consider response as closed after raising an exception. Technically it can contain a partial body but there is no any guarantee. There is no reason to read it, the body could be very huge, 1GiB is not a limit. If you need a response content for non-200 -- read it explicitly.
Alternatively, consider using the httpx library in this way. (It is widely used in conjunction with FastAPI):
def raise_on_4xx_5xx(response):
response.raise_for_status()
async with httpx.AsyncClient(event_hooks={'response': [raise_on_4xx_5xx]}) as client:
try:
r = await client.get('http://httpbin.org/status/418')
except httpx.HTTPStatusError as e:
print(e.response.text)