Python requests - print entire http request (raw)?
使用
我不想只是标题,我想要请求行,标题和内容打印输出。 是否有可能看到最终由HTTP请求构造的内容?
由于v1.2.3请求添加了PreparedRequest对象。根据文档"它包含将发送到服务器的确切字节"。
可以使用它来打印请求,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import requests req = requests.Request('POST','http://stackoverflow.com',headers={'X-Custom':'Test'},data='a=1&b=2') prepared = req.prepare() def pretty_print_POST(req): """ At this point it is completely built and ready to be fired; it is"prepared". However pay attention at the formatting used in this function because it is programmed to be pretty printed and may differ from the actual request. """ print('{} {} {} {}'.format( '-----------START-----------', req.method + ' ' + req.url, ' '.join('{}: {}'.format(k, v) for k, v in req.headers.items()), req.body, )) pretty_print_POST(prepared) |
产生:
1 2 3 4 5 6 | -----------START----------- POST http://stackoverflow.com/ Content-Length: 7 X-Custom: Test a=1&b=2 |
然后你可以发送实际的请求:
1 2 | s = requests.Session() s.send(prepared) |
这些链接是可用的最新文档,因此它们可能会更改内容:
高级 - 准备好的请求和API - 低级别课程
注意:这个答案已经过时了。较新版本的
从
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | -> r= requests.get("http://google.com") /usr/local/lib/python2.7/dist-packages/requests/api.py(55)get() -> return request('get', url, **kwargs) /usr/local/lib/python2.7/dist-packages/requests/api.py(44)request() -> return session.request(method=method, url=url, **kwargs) /usr/local/lib/python2.7/dist-packages/requests/sessions.py(382)request() -> resp = self.send(prep, **send_kwargs) /usr/local/lib/python2.7/dist-packages/requests/sessions.py(485)send() -> r = adapter.send(request, **kwargs) /usr/local/lib/python2.7/dist-packages/requests/adapters.py(324)send() -> timeout=timeout /usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py(478)urlopen() -> body=body, headers=headers) /usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py(285)_make_request() -> conn.request(method, url, **httplib_request_kw) /usr/lib/python2.7/httplib.py(958)request() -> self._send_request(method, url, body, headers) |
在
由于没有任何钩子可以做你想做的事情,作为最后的手段,你可以使用补丁
唉,不用多说,解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 | import requests import httplib def patch_send(): old_send= httplib.HTTPConnection.send def new_send( self, data ): print data return old_send(self, data) #return is not necessary, but never hurts, in case the library is changed httplib.HTTPConnection.send= new_send patch_send() requests.get("http://www.python.org") |
产生输出:
1 2 3 4 5 | GET / HTTP/1.1 Host: www.python.org Accept-Encoding: gzip, deflate, compress Accept: */* User-Agent: python-requests/2.1.0 CPython/2.7.3 Linux/3.2.0-23-generic-pae |
1 2 3 4 | import requests response = requests.post('http://httpbin.org/post', data={'key1':'value1'}) print(response.request.body) print(response.request.headers) |
我正在使用请求版本2.18.4和Python 3
更好的想法是使用requests_toolbelt库,它可以将请求和响应转储为字符串,供您打印到控制台。它使用上述解决方案无法处理的文件和编码来处理所有棘手的情况。
它就像这样简单:
1 2 3 4 5 6 | import requests from requests_toolbelt.utils import dump resp = requests.get('https://httpbin.org/redirect/5') data = dump.dump_all(resp) print(data.decode('utf-8')) |
来源:https://toolbelt.readthedocs.org/en/latest/dumputils.html
您只需输入以下命令即可安装:
1 | pip install requests_toolbelt |
这是一个代码,它使相同,但带有响应头:
1 2 3 4 5 6 7 8 9 10 11 | import socket def patch_requests(): old_readline = socket._fileobject.readline if not hasattr(old_readline, 'patched'): def new_readline(self, size=-1): res = old_readline(self, size) print res, return res new_readline.patched = True socket._fileobject.readline = new_readline patch_requests() |
我花了很多时间寻找这个,所以如果有人需要,我就把它留在这里。
我使用以下函数来格式化请求。它就像@AntonioHerraizS,除了它还会在体内打印JSON对象,它标记了请求的所有部分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | format_json = functools.partial(json.dumps, indent=2, sort_keys=True) indent = functools.partial(textwrap.indent, prefix=' ') def format_prepared_request(req): """Pretty-format 'requests.PreparedRequest' Example: res = requests.post(...) print(format_prepared_request(res.request)) req = requests.Request(...) req = req.prepare() print(format_prepared_request(res.request)) """ headers = ' '.join(f'{k}: {v}' for k, v in req.headers.items()) content_type = req.headers.get('Content-Type', '') if 'application/json' in content_type: try: body = format_json(json.loads(req.body)) except json.JSONDecodeError: body = req.body else: body = req.body s = textwrap.dedent(""" REQUEST ======= endpoint: {method} {url} headers: {headers} body: {body} ======= """).strip() s = s.format( method=req.method, url=req.url, headers=indent(headers), body=indent(body), ) return s |
我有一个类似的功能来格式化响应:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | def format_response(resp): """Pretty-format 'requests.Response'""" headers = ' '.join(f'{k}: {v}' for k, v in resp.headers.items()) content_type = resp.headers.get('Content-Type', '') if 'application/json' in content_type: try: body = format_json(resp.json()) except json.JSONDecodeError: body = resp.text else: body = resp.text s = textwrap.dedent(""" RESPONSE ======== status_code: {status_code} headers: {headers} body: {body} ======== """).strip() s = s.format( status_code=resp.status_code, headers=indent(headers), body=indent(body), ) return s |