django的HttpRequest.META字典是如何填充的?

1 投票
3 回答
1388 浏览
提问于 2025-04-18 15:30

django的 HttpRequest.META 字典 是怎么填充的?所有的键和值都是来自客户端发送的http请求头吗?如果是这样,我是不是可以认为这些值都是可以被客户端修改的?

我问这个问题是因为在我Chrome的调试控制台中找不到大部分显示的键。而且其中一些键显然和客户端无关,比如 通过Shibboleth登录的用户的用户名。我不明白为什么这种数据会先从服务器发送到客户端,然后再通过http请求返回给服务器。

3 个回答

0

我在尝试在Django中添加自定义的request.META键时遇到了同样的问题。

根据官方文档:

除了CONTENT_LENGTH和CONTENT_TYPE这两个,其他的HTTP头信息都会被转换成META键。转换的方式是把所有字符变成大写,把连字符(-)替换成下划线(_),并在名字前加上HTTP_前缀。例如,一个叫做X-Bender的头信息会被转换成META键HTTP_X_BENDER。

需要注意的是,runserver会去掉所有名字中带下划线的头信息,所以你在META中看不到它们。这是为了防止因为下划线和连字符的混淆而导致的头信息伪造,因为在WSGI环境变量中,它们都会被规范化为下划线。这种行为与Nginx和Apache 2.4+等Web服务器是一致的。

这意味着如果你添加一个名为"new_meta"的头信息,它会被转换为"HTTP_NEW_META";如果添加一个名为"new"的头信息,它会被转换为"HTTP_NEW"。

顺便提一下,request.META中没有"HTTP_"前缀的其他键是来自服务器环境的,你可以通过在服务器主机上运行export命令来找到它们。

1

我觉得你说得对,数据是不能完全信任的。你和客户之间只有一个服务器,比如nginx,它可能会修改一些信息,比如只允许特定大小的数据等等。不过我也可能错了 :)

2

大部分的 request.META 信息来自于脚本的运行环境,具体来说,是来自 django.core.handler.wsgi.WSGIRequest 这个类的初始化过程。我这里主要说的是 wsgi 处理器,但据我所知,目前它是唯一一个具体的 handler 子类,其他的部署选项最终都是以某种方式使用 wsgi(比如 django.core.server.fastcgidjango.core.server.basehttp)。

换句话说,你在 request.META 中看到的信息,取决于调用脚本传入了什么,而这些又依赖于前端服务器等因素。

撰写回答