aiohttp自定义Connector请求挂起,返回对象需实现哪些方法?
问题描述
我有一个名为Channel的类,用于处理自定义数据流,主要包含read()、write()、open()、end()、close()方法以及incoming/outcoming_queue属性,它们能正确处理并控制各类请求。我尝试将其作为自定义Connector使用,让用户可通过以下代码发起请求:
async with aiohttp.ClientSession(connector=self.custom_connector) as session: async with session.get(url) as resp: return await resp.text()
由custom_connector处理请求目标。我的CustomConnector实现如下:
class CustomConnector(aiohttp.BaseConnector): async def _create_connection(self, req, traces, timeout): # duplex_channel是上述Channel类的实例 return duplex_channel
但目前代码在session.get(url)处挂起,我认为原因是Channel类不符合aiohttp的预期。文档提到ResponseHandler但未深入说明。请问_create_connection方法返回的对象需要实现哪些方法?我可能遗漏了什么?
解决方案
aiohttp的_create_connection方法返回的对象必须遵循aiohttp连接协议,你的Channel类缺少关键接口实现,才导致请求挂起。具体需要实现以下核心内容:
1. 必须实现的异步I/O方法
async def read(n: int) -> bytes:你已有该方法,但要确保返回最多n字节的数据;当数据流结束时,需抛出asyncio.IncompleteReadError或返回空字节串(不同版本要求有差异,可参考aiohttp内部StreamReader的实现逻辑)。async def write(data: bytes):保证写入操作是异步的,能正确处理缓冲区,写完后触发aiohttp的后续流程。async def close():关闭连接时要正确清理资源,同时触发结束信号,让aiohttp感知连接已终止。
2. 关键的协议兼容属性/方法
transport属性:aiohttp会依赖该属性获取底层传输信息,可返回一个模拟的transport对象,至少实现is_closing()方法(返回布尔值表示连接是否关闭)。protocol属性:需要关联符合aiohttpResponseHandler协议的对象,或至少实现connection_made()、data_received()等方法,用于处理HTTP响应的解析流程。async def start_tls(...):如果涉及HTTPS请求,必须实现TLS握手方法,否则HTTPS请求会直接失败。
3. 你可能遗漏的核心逻辑
aiohttp的连接对象需要主动触发HTTP响应的解析流程,你的Channel类仅处理了数据流,但未将接收到的数据传递给aiohttp的响应处理器:
- 在
Channel的read()方法获取到数据后,需调用aiohttp协议对象的data_received()方法,把数据喂给HTTP解析器。 - 当数据流结束时,调用协议对象的
eof_received()方法,通知aiohttp响应已完成。
另外,_create_connection方法的标准返回格式是包含transport和protocol的元组,而非直接返回Channel实例:
return (transport, protocol)
你可以把Channel作为底层数据流处理模块,封装到自定义的protocol和transport对象中,再返回给aiohttp。
内容的提问来源于stack exchange,提问作者vilal32
相关产品推荐
相关产品推荐

