Евг*_*лов 5 python python-asyncio aiohttp
我使用 aiohttp 来发出 post 请求。我需要在发送请求之前获取post请求中准备好的数据。因此,我尝试在 aiohttp 中找到一种与requests 库中的准备方法类似的方法。是否可以?
这只是 aiohttp 中的一个概念验证解决方法,用于在发送请求之前获取请求的正文,并同时执行操作(例如通常签名和添加签名标头)。
免责声明:我不建议在生产环境(或严肃的场合)中使用它。因为它依赖于 aiohttp 中非公开且未记录的函数或属性。如果 aiohttp 的内部实现发生变化,它可能随时崩溃。
import aiohttp
import asyncio
import hashlib
import hmac
SECRET_KEY = '__SECRET_KEY__'
class HMACBodySignClientRequest(aiohttp.ClientRequest):
def update_body_from_data(self, body) -> None:
"""bad: hook this internal method to get body and inject signature (may fail anytime if internal changes)"""
super().update_body_from_data(body)
if body is None: # use `body` rather than `self.body` is expected.
return
body = self.body._value or b'' # bad: access to protected property (may not available)
signature = hmac.new(SECRET_KEY.encode('utf-8'), body, digestmod=hashlib.sha256)
self.headers['X-Signature'] = signature.hexdigest()
async def aiohttp_body_sign_workaround():
url = 'https://httpbin.org/api'
data = {'foo': 'bar'}
async with aiohttp.ClientSession(
request_class=HMACBodySignClientRequest) as session: # <-- auto add signature via `request_class`
async with session.post(url=url, json=data) as response:
print(response.request_info)
asyncio.run(aiohttp_body_sign_workaround())
Run Code Online (Sandbox Code Playgroud)
在 aiohttp 3.8.5 上测试,在任何其他版本中可能会失败。
请注意,这种方法是一种“黑魔法”,可能只适用于某些微不足道的情况,例如小数据或非流请求。使用风险自负。
在 aiohttp 当前的内部设计中,有一个内部属性_request_class: ClientRequeston ClientSession,它委托实际的请求生成。
在某些时候,请求主体字节可能可以获取。
发现调用该ClientRequest方法后,访问可能会显示主体字节。update_body_from_data()self.body._value
幸运的是,可以在使用参数_request_class初始化 a 时指定该属性。这意味着我们可以子类化并覆盖/挂钩该方法以添加自定义逻辑(在本例中,将主体的 HMAC 签名添加到标头)。ClientSessionrequest_classClientRequestupdate_body_from_data()
是的,它依赖于内部细节,所以正如我所说,这只是一个概念验证。
| 归档时间: |
|
| 查看次数: |
368 次 |
| 最近记录: |