首页 > 解决方案 > AIOHTTP 在调用 raise_for_status 时具有请求正文/内容/文本

问题描述

我正在使用FastAPIwith aiohttp,我为持久会话构建了一个单例,并使用它在启动时打开会话并在关闭时关闭它。

需求response身体很珍贵,万一发生故障,我必须把它和其他细节一起记录下来。

因为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返回正文(response.text()),我可以启动会话ClientSession(raise_for_status=True)并编写一个干净的代码:

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

有没有办法强制以某种方式raise_for_status返回有效载荷/主体,也许在初始化ClientSession

谢谢您的帮助。

标签: pythonaiohttpfastapi

解决方案


aiohttp和是不可能的raise_for_status。正如@Andrew Svetlov在这里回答的那样:

引发异常后将响应视为关闭。从技术上讲,它可以包含部分主体,但没有任何保证。没有理由阅读它,主体可能非常巨大,1GiB 不是限制。如果您需要非 200 的响应内容,请明确阅读。

或者,考虑以这种方式使用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)

推荐阅读