获取HTTP请求,如通过有线传输(Django)
如果您有一个django请求对象,是否可以像通过有线传输一样通过测试环获取http请求 当然,如果使用https,纯文本不会加密 我想存储bytestring,以便稍后对其进行分析 充其量我想访问真正的bytestring。从request.META、request.GET和friends创建一个bytestring可能与原来的不同获取HTTP请求,如通过有线传输(Django),django,httprequest,Django,Httprequest,如果您有一个django请求对象,是否可以像通过有线传输一样通过测试环获取http请求 当然,如果使用https,纯文本不会加密 我想存储bytestring,以便稍后对其进行分析 充其量我想访问真正的bytestring。从request.META、request.GET和friends创建一个bytestring可能与原来的不同 更新:似乎不可能获得原始字节。然后问题是:如何构造一个大致与原始内容类似的bytestring?基本答案是否定的,Django没有访问原始请求的权限,事实上它甚至没
更新:似乎不可能获得原始字节。然后问题是:如何构造一个大致与原始内容类似的bytestring?基本答案是否定的,Django没有访问原始请求的权限,事实上它甚至没有解析原始HTTP请求的代码 这是因为Django与许多其他Python web框架一样,HTTP请求/响应处理在其核心是一个WSGI应用程序 前端/代理服务器(如Apache或nginx)和应用服务器(如uWSGI或gunicorn)的工作是处理请求(如转换和剥离头文件),并将其转换为可由Django处理的对象 作为一个实验,您实际上可以自己包装Django的WSGI应用程序,并查看Django在收到请求时使用了什么 编辑项目的wsgi.py并添加一些非常基本的wsgi中间件:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
class MyMiddleware:
def __init__(self, app):
self._app = app
def __call__(self, environ, start_response):
import pdb; pdb.set_trace()
return self._app(environ, start_response)
# Wrap Django's WSGI application
application = MyMiddleware(get_wsgi_application())
现在,如果您启动devserver./manage.py运行服务器并向Django应用程序发送请求。您将进入调试器
这里唯一感兴趣的是environ dict。看看它,你会发现它与Django的request.META中的内容几乎相同。环境宣言的内容详见
知道了这一点,你能得到的最好的东西就是将环境中的项目拼凑到一个类似HTTP请求的东西上
但是为什么呢?如果您有一个environdict,那么您就有了复制Django请求所需的所有信息。实际上不需要将此转换回HTTP请求
事实上,正如您现在所知,调用Django的WSGI应用程序根本不需要HTTP请求。您所需要的只是一个带有所需键和可调用项的environ dict,以便Django能够转发响应
因此,要分析请求,甚至能够重播它们,您只需要能够重新创建一个有效的环境
在Django中,最简单的方法是将request.META和request.body序列化为JSON dict
如果您确实需要类似HTTP请求的内容,并且无法升级到Web服务器来记录此信息,则您只需将request.META和request.body中的可用信息拼凑在一起,需要注意的是,这不是原始HTTP请求的真实表示。正如其他人指出的,这是不可能的,因为Django不与原始请求交互 您可以尝试像这样重新构造请求
def reconstruct_request(request):
headers = ''
for header, value in request.META.items():
if not header.startswith('HTTP'):
continue
header = '-'.join([h.capitalize() for h in header[5:].lower().split('_')])
headers += '{}: {}\n'.format(header, value)
return (
'{method} HTTP/1.1\n'
'Content-Length: {content_length}\n'
'Content-Type: {content_type}\n'
'{headers}\n\n'
'{body}'
).format(
method=request.method,
content_length=request.META['CONTENT_LENGTH'],
content_type=request.META['CONTENT_TYPE'],
headers=headers,
body=request.body,
)
注意,这不是一个完整的示例,只是概念证明
不,您不能,因为是wsgi处理程序(例如uwsgi、gunicorn)解析原始请求并将其传递给Django。Django从未看到原始请求。@solarissmoke感谢您的评论。我根据我遇到的这个项目更新了这个问题,这个项目存储了请求和响应。但我没有研究实际的格式: