Emanuel
Emanuel

Reputation: 722

AIOHTTP having request body/content/text when calling raise_for_status

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.

Upvotes: 5

Views: 5063

Answers (1)

alex_noname
alex_noname

Reputation: 32233

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)

Upvotes: 4

Related Questions