使用 aiohttp 转储请求标头

bor*_*yer 4 python python-3.x aiohttp

我想显示请求的所有 HTTP 标头(我添加的和自动生成的)。我尝试使用跟踪(https://aiohttp.readthedocs.io/en/stable/tracing_reference.html#aiohttp-client-tracing-reference):

#!/usr/bin/env python3                                                                                                      

import aiohttp
import asyncio

async def on_request_start(session, trace_config_ctx, params):
    print("Starting %s request for %s. I will send: %s" % (params.method, params.url, params.headers))

async def on_request_end(session, trace_config_ctx, params):
    print("Ending %s request for %s. I sent: %s" % (params.method, params.url, params.headers))

async def fetch(session, url):
    async with session.get(url) as response:
        return response

async def main():
    trace_config = aiohttp.TraceConfig()
    trace_config.on_request_start.append(on_request_start)
    trace_config.on_request_end.append(on_request_end)
    async with aiohttp.ClientSession(trace_configs=[trace_config]) as session:
        r = await fetch(session, 'http://stackoverflow.com')
        print(r)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)

通过这段代码,我得到了方法和 URL,但 headers 的字典始终为空:

% ./test-debug.py
Starting GET request for http://stackoverflow.com. I will send: <CIMultiDict()>
Ending GET request for https://stackoverflow.com/. I sent: <CIMultiDict()>
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

Python 3.7.2

% pip show aiohttp
Name: aiohttp
Version: 3.5.4
Summary: Async http client/server framework (asyncio)
Home-page: https://github.com/aio-libs/aiohttp
Author: Nikolay Kim
Author-email: fafhrd91@gmail.com
License: Apache 2
Location: /usr/lib/python3.7/site-packages
Requires: async-timeout, attrs, multidict, yarl, chardet
Required-by: 
Run Code Online (Sandbox Code Playgroud)

Pat*_*zek 6

仔细阅读库源代码后,request_start为时过早,它甚至在创建请求对象之前就被调用,因此它永远不会看到完整的请求及其标头;计时器在循环发送内容之后启动。

但是,request_end您可以访问完整的响应对象,该对象与请求对象以及所有标头相关联。

有了这个改变:

async def on_request_end(session, trace_config_ctx, params):
    print("Ending %s request for %s. I sent: %s" % (params.method, params.url, params.headers))
    print('Sent headers: %s' % params.response.request_info.headers)
Run Code Online (Sandbox Code Playgroud)

我得到:

Sent headers: <CIMultiDictProxy('Host': 'stackoverflow.com', 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Python/3.7 aiohttp/3.5.4', 'Cookie': 'prov=f4fad342-c1f7-bcc2-5d25-0e30ae5cdbf6')>
Run Code Online (Sandbox Code Playgroud)

您可能还需要查看params.response.history重定向的情况。它是一个对象序列ClientResponse,因此您应该能够调用request_info.headers它们中的每一个。