如果您有django请求对象,是否有可能像通过有线传输一样将http请求作为字节字符串获取?
当然是纯文本(如果使用https,则不会加密)。
我想存储字节串以便以后分析。
充其量我想访问真正的字节串。从request.META,request.GET和朋友创建一个字节字符串可能与原始字符串不同。
更新:看来不可能到达原始字节。然后的问题是:如何构造一个大致看起来像原始的字节串?
答案 0 :(得分:3)
正如其他人指出的那样,这是不可能的,因为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,
)
注意,这不是一个完整的示例,仅是概念证明
答案 1 :(得分:1)
基本答案是“否”,Django没有访问原始请求的权限,实际上,它甚至没有解析原始HTTP请求的代码。
这是因为Django(像许多其他Python Web框架一样)的HTTP请求/响应处理是WSGI应用程序(WSGI specification)的核心。
前端/代理服务器(如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 runserver
)并将请求发送到Django应用程序。您将进入调试器。
这里唯一有趣的是environ
字典。戳一下它,您会发现它与Django request.META
中的发现几乎相同。 (environ
字典的内容在this section of the WSGI spec中有详细说明。)
知道这一点,最好的办法是将environ
字典中的项目拼凑成远程类似于HTTP请求的内容。
但是为什么呢?如果您有一个environ
字典,那么您拥有复制Django请求所需的所有信息。确实没有必要将其转换回HTTP请求。
事实上,正如您现在所知道的,您根本不需要HTTP请求即可调用Django的WSGI应用程序。您需要做的是environ
字典,其中包含必需的键和可调用键,以便Django可以中继响应。
因此,要分析请求(甚至能够重放请求),您只需能够重新创建有效的environ
字典即可。
要在Django中这样做,最简单的选择是将request.META
和request.body
序列化为JSON字典。
如果您确实需要类似HTTP请求的内容(并且无法升级到例如Web服务器来记录此信息),则只需将{{1}中的可用信息整理在一起}和request.META
,但要注意,这不是原始HTTP请求的真实表示。