Python请求 – 打印整个HTTP请求(原始)?

在使用requests模块时 ,有没有办法打印原始的HTTP请求?

我不想只是标题,我想要的行,标题和内容打印输出。 是否有可能看到最终从HTTP请求构造?

由于v1.2.3请求添加了PreparedRequest对象。 根据文档“它包含将发送到服务器的确切字节数”。

我们可以用它来打印请求,如下所示:

 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('{}\n{}\n{}\n\n{}'.format( '-----------START-----------', req.method + ' ' + req.url, '\n'.join('{}: {}'.format(k, v) for k, v in req.headers.items()), req.body, )) pretty_print_POST(prepared) 

这产生:

 -----------START----------- POST http://stackoverflow.com/ Content-Length: 7 X-Custom: Test a=1&b=2 

然后你可以用这个发送实际的请求:

 s = requests.Session() s.send(prepared) 

这些链接是可用的最新文档,因此它们可能会在内容上发生变化: 高级 – 准备好的请求和API – 低级别的类

注意:这个答案已经过时了。 更新版本的requests支持直接获取请求内容,如Antonio Herriz的答案文件

不可能从请求中获取requests真实原始内容,因为它仅处理更高级别的对象,例如标头方法typesrequests使用urllib3发送请求,但urllib3也不处理原始数据 – 它使用httplib 。 以下是一个请求的代表性堆栈跟踪:

 -> 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) 

httplib机制内部,我们可以看到HTTPConnection._send_request间接使用HTTPConnection._send_output ,最终创build原始请求正文(如果存在),并使用HTTPConnection.send分别发送它们。 send终于到达sockets。

既然没有你想做的事情的钩子,作为最后的手段,你可以猴子补丁httplib获取内容。 这是一个脆弱的解决scheme,如果httplib改变了,你可能需要修改它。 如果您打算使用此解决scheme分发软件,则可能需要考虑打包httplib而不是使用系统,这很容易,因为它是纯粹的Python模块。

唉,不用多说,解决办法:

 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") 

这产生了输出:

 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 

更好的办法是使用requests_toolbelt库,它可以将请求和响应转储为string,以便打印到控制台。 它处理所有棘手的情况与上述解决scheme不能很好地处理文件和编码。

这很简单:

 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

您可以通过键入以下命令来安装它:

 pip install requests_toolbelt 

这里是一个代码,它使得相同的,但与响应标题:

 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() 

我花了很多时间寻找这个,所以如果有人需要的话,我就把它留在这里。

如果您的发布数据不是私有的,您可以使用requestb.in来检查请求。

 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