Python 如何在不中断流的情况下安全地从asyncio读取ReaderStream

Python 如何在不中断流的情况下安全地从asyncio读取ReaderStream,python,tcp,proxy,python-asyncio,Python,Tcp,Proxy,Python Asyncio,我正在尝试构建一个中间人代理服务器,将客户端请求转发到我的应用程序中预定义的各种代理服务。因此,为了做到这一点,我需要区分客户对服务的请求。 只要我不取消注释#data=wait client\u reader.read(2048),下面的代码就可以工作,我可以从中解析标题。i、 e.如果我执行了该代码, 如果我使用未注释的代码行执行此操作: r = requests.get('http://api.ipify.org/', headers = {'Proxy-Type':'custom'},

我正在尝试构建一个中间人代理服务器,将客户端请求转发到我的应用程序中预定义的各种代理服务。因此,为了做到这一点,我需要区分客户对服务的请求。
只要我不取消注释
#data=wait client\u reader.read(2048)
,下面的代码就可以工作,我可以从中解析标题。i、 e.如果我执行了该代码,
如果我使用未注释的代码行执行此操作:

r = requests.get('http://api.ipify.org/', headers = {'Proxy-Type':'custom'}, proxies={'http':'http://127.0.0.1:9911'}) 
r.content

async def proxy_data(reader, writer, connection_string):

  try:
    while True:
      data = await reader.read(2048)
      if not data:
        break
      writer.write(data)
      await writer.drain()
  except Exception as e:
    raise
  finally:
    writer.close()

async def accept_client(client_reader, client_writer):

  try:
    # Get proxy service - [Proxy-Type] from header via client_reader
    # Set remote_address and remote_port based on it

    # data = await client_reader.read(2048)

    (remote_reader, remote_writer) = await asyncio.wait_for(
    asyncio.open_connection(host = remote_address, port = remote_port),
      timeout = 30)
  except asyncio.TimeoutError:
    client_writer.close()
  except Exception as e:
    client_writer.close()
  else:
    # Pipe the streams
    asyncio.ensure_future(proxy_data(client_reader, remote_writer))
    asyncio.ensure_future(proxy_data(remote_reader, client_writer))

def main():

  def handle_client(client_reader, client_writer):
    asyncio.ensure_future(
      accept_client(
        client_reader = client_reader,
        client_writer = client_writer
      )
    )


  loop = asyncio.get_event_loop()
  try:
    server = loop.run_until_complete(
      asyncio.start_server(
        handle_client, host = '127.0.0.1', port = 9911))
  except Exception as e:
    logger.error('Bind error: {}'.format(e))
    sys.exit(1)

  for s in server.sockets:
    logger.debug('Proxy broker listening on {}'.format(s.getsockname()))

  try:
    loop.run_forever()
  except KeyboardInterrupt:
    pass
if __name__ == '__main__':
  main()

有人能指出这里的问题或如何有条件地打开连接吗?

通过重新输入客户端读取器()

感谢Vincent的评论,指出了请求篡改的情况,并将请求重建回其原始形式

async def accept_client(client_reader, client_writer):

  try:
    # Get proxy service - [Proxy-Type] from header via client_reader
    # Set remote_address and remote_port based on it

    data = await client_reader.read(2048)

    # -------- Edited --------

    # perform operations based on data and obtain remote_address, remote_port

    (remote_reader, remote_writer) = await asyncio.wait_for(
    asyncio.open_connection(host = remote_address, port = remote_port),
      timeout = 30)
  except asyncio.TimeoutError:
    client_writer.close()
  except Exception as e:
    client_writer.close()
  else:

    # Write the data to remote
    remote_writer.write(data)
    await remote_writer.drain()

    # Pipe the streams
    asyncio.ensure_future(proxy_data(client_reader, remote_writer))
    asyncio.ensure_future(proxy_data(remote_reader, client_writer))

也许您忘记了在管道化流之前在远程写入程序中写入头数据?但是远程写入程序不应该依赖于打开的连接吗?i、 e.远程_writer不应该基于客户端头中请求的自定义代理服务吗?是的,但您不希望通过提取代理信息来破坏请求格式。您必须找到一种方法来重建可由远程服务处理的有效请求。确实如此,但由于我不希望以任何方式篡改该请求,因此只要在
accept\u client
中有一个本地\u reader流的tmp\u reader副本,并针对该条件进行处理就可以了。这似乎不工作,也只是一个复制,我想这与它是一个科罗?!通过使用
client\u reader.feed\u data(data)
修复实际上,在保存数据之后,
feed\u data
是由底层流协议调用的,我认为这样使用是不安全的。例如,该协议可能会从客户端接收更多数据,并在您反馈报头之前对其进行反馈,从而破坏请求。我会使用
remote\u writer.write(data)
(在管道传输流之前)。我不确定是否可以使用
remote\u writer
作为实际定义
remote\u地址的条件,而
remote\u port
将取决于从
本地\u reader
中的头获取的数据。比如说,如果客户端头包含
'Proxy-Type':'tor'
,那么我的远程地址将是
tor ip
的地址。当然可以,但这应该不是问题。我将使用以下工作流:从客户端读取头,获取远程地址,创建远程连接,将头写入远程,通过管道连接客户端和远程。太棒了!。再次感谢