aiohttp:当请求状态码不是 2XX 时获取服务器的响应
aiohttp: Getting a server's response when the request status code is not 2XX
我正在使用 aiohttp 进行异步 http 请求,当请求 returns 出现 4XX 错误时,我不知道如何从服务器获取响应。
async def login(self, username: str, password: str) -> None:
...
async with aiohttp.ClientSession(headers=self._headers) as session:
async with session.post(route, data=data, headers=self._headers) as resp:
if resp.ok:
response = await resp.json()
self._headers['Authorization'] = 'Bearer ' + response['access_token']
else:
response = await resp.json()
raise InvalidGrant(response)
如果响应 returns 一个 2XX 代码,使用 resp.json()
就可以正常工作,但是当它 returns 一个 4XX 错误(在本例中为 400
)时,它会引发a aiohttp.client_exceptions.ClientConnectionError
并且不让我得到服务器发送的响应(这是我需要的,因为服务器 returns 某种错误消息比 Bad Request
更具描述性)。如果请求不成功,是否无法通过 aiohttp 获得响应?
出现此问题的原因是 response.ok
的副作用。在旧版本的 aiohttp(3.7 及更低版本)中,response.ok
调用了 response.raise_for_status()
,它关闭了 TCP 会话并导致无法再读取服务器的响应。
要解决此问题,您只需将 response = await resp.json()
移动到 response.ok
行上方,这样您就可以预先保存响应。例如:
async def login(self, username: str, password: str) -> None:
...
async with aiohttp.ClientSession(headers=self._headers) as session:
async with session.post(route, data=data, headers=self._headers) as resp:
response = await resp.json()
if resp.ok:
self._headers['Authorization'] = 'Bearer ' + response['access_token']
else:
raise InvalidGrant(response)
此问题已在 aiohttp 3.8 中修复,但是:https://github.com/aio-libs/aiohttp/pull/5404
我正在使用 aiohttp 进行异步 http 请求,当请求 returns 出现 4XX 错误时,我不知道如何从服务器获取响应。
async def login(self, username: str, password: str) -> None:
...
async with aiohttp.ClientSession(headers=self._headers) as session:
async with session.post(route, data=data, headers=self._headers) as resp:
if resp.ok:
response = await resp.json()
self._headers['Authorization'] = 'Bearer ' + response['access_token']
else:
response = await resp.json()
raise InvalidGrant(response)
如果响应 returns 一个 2XX 代码,使用 resp.json()
就可以正常工作,但是当它 returns 一个 4XX 错误(在本例中为 400
)时,它会引发a aiohttp.client_exceptions.ClientConnectionError
并且不让我得到服务器发送的响应(这是我需要的,因为服务器 returns 某种错误消息比 Bad Request
更具描述性)。如果请求不成功,是否无法通过 aiohttp 获得响应?
出现此问题的原因是 response.ok
的副作用。在旧版本的 aiohttp(3.7 及更低版本)中,response.ok
调用了 response.raise_for_status()
,它关闭了 TCP 会话并导致无法再读取服务器的响应。
要解决此问题,您只需将 response = await resp.json()
移动到 response.ok
行上方,这样您就可以预先保存响应。例如:
async def login(self, username: str, password: str) -> None:
...
async with aiohttp.ClientSession(headers=self._headers) as session:
async with session.post(route, data=data, headers=self._headers) as resp:
response = await resp.json()
if resp.ok:
self._headers['Authorization'] = 'Bearer ' + response['access_token']
else:
raise InvalidGrant(response)
此问题已在 aiohttp 3.8 中修复,但是:https://github.com/aio-libs/aiohttp/pull/5404