获取通过有线传输的HTTP请求(Django)

时间:2018-10-06 08:18:18

标签: django httprequest

如果您有django请求对象,是否有可能像通过有线传输一样将http请求作为字节字符串获取?

当然是纯文本(如果使用https,则不会加密)。

我想存储字节串以便以后分析。

充其量我想访问真正的字节串。从request.META,request.GET和朋友创建一个字节字符串可能与原始字符串不同。

更新:看来不可能到达原始字节。然后的问题是:如何构造一个大致看起来像原始的字节串?

2 个答案:

答案 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.METArequest.body序列化为JSON字典。

如果您确实需要类似HTTP请求的内容(并且无法升级到例如Web服务器来记录此信息),则只需将{{1}中的可用信息整理在一起}和request.META,但要注意,这不是原始HTTP请求的真实表示。