AIOHTTP 在调用 raise_for_status 时有请求 body/content/text

AIOHTTP having request body/content/text when calling raise_for_status

我将 FastAPIaiohttp 一起使用,我为持久性 session 构建了一个单例,我用它在启动时打开 session 并且在关机时关闭它。

需求:responsebody在失败的情况下很珍贵我必须用其他细节。

因为 raise_for_status 的行为方式,我不得不编写那些处理每个 HTTP 方法的丑陋函数,这是其中之一:

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

如果我能指望 raise_for_status 到 return 还有 body (response.text()), 我可以启动 session ClientSession(raise_for_status=True) 并编写一个干净的代码:

response = await self.session.post(url=url, json=json, headers=headers)

有没有办法以某种方式强制 raise_for_status 到 return 以及 payload/body,也许在 ClientSession 的初始化中?

感谢您的帮助。

aiohttpraise_for_status 是不可能的。正如@Andrew Svetlov 回答的那样 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.

或者,考虑以这种方式使用 httpx 库。 (广泛与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)