特别是,Werkzeug 在内部将“Transfer-Encoding”或“X-PoweredBy”类型的标头分别转换为“HTTP_TRANSFER_ENCODING”和“X_POWERED_BY”。 但是,如果两个标头“App-Header-1”和“App_Header_1”都出现在请求中——或者甚至只是“App_Header_1”——两者都将在内部以相同的方式存储,而且 Werkzeug 不区分这两者. 此行为不符合 RFC2616 HTTP 1.1 规范,其中 Header 名称可以是任何没有控制或分隔符的有效标记。 这有很多问题,就好像一个带有“App_Header_1”的请求会被转换为“HTTP_APP_HEADER_1”,现在像 Flask 这样的框架会将它解释为“App-Header-1”,这不一样,并传递这些值在任何合理的比较策略下,依赖于正确行为的系统将失败为 "App_Header_1" != "App-Header-1"。
这种行为是由 WSGI 规范本身引起的,并且 Werkzeug 不可能在仍然遵守 WSGI 规范的同时区分这两个标头。 我不知道在实践中这会成为问题的任何情况。
顺便说一下,RFC 2616 已被弃用,但较新的 RFC 无论如何都不会改变这方面的任何内容。
Werkzeug 也不负责在语法级别解析或编写 HTTP 请求或响应。 这是由您选择的任何 WSGI 服务器完成的。 Werkzeug 确实有一个内置服务器,但它只是从标准库扩展了 WSGI 服务器。
如果您指的是 PEP 3333,则该行为不是由 WSGI 规范引起的。
PEP 3333 指出:
HTTP_ 变量
对应于客户端提供的 HTTP 请求标头的变量(即名称以“HTTP_”开头的变量)。 这些变量的存在与否应与请求中相应的 HTTP 标头的存在与否相对应。
规范中没有关于以不同方式处理下划线的内容。 事实上,您不符合 PEP 3333 也是因为我不知道哪个标头存在或不存在,即是否存在“App_H”或“App-H”。
WSGI 是 CGI 的 Python 特定端口。 PEP 0333 引用了 CGI 规范来定义“CGI 环境变量”,其中指出:
The HTTP header field name is converted to upper case, has all occurrences of "-" replaced with "_" and has `HTTP_' prepended to give the meta-variable name.
见https://tools.ietf.org/html/rfc3875#section -4.1.18
所有这些都无关紧要,因为 Werkzeug 在大多数情况下不解析原始 HTTP 请求,也不生成 WSGI 环境。 它解析 WSGI 环境。 我不明白你为什么要针对这个特定的实现提交这个问题。 不要射击使者。
基本上这里有很多来自 CGI 的遗产,这些遗产是由 WSGI 继承的,这是 Werkzeug 试图实现的。
我真的不是故意要打架; 但这是一个安全隐患的问题,特别是对于位于“传统”-ish 应用程序网关后面的 Web 服务器,这些网关在包含下划线的标头中传递敏感/特定于应用程序的信息而不过滤其他标头(我有具体的例子,也就是说,这是实际上是实践中的一个问题,您在最初的评论中已将其驳回)。 CGI 已有 20 多年的历史,因此 WSGI 和 HTTP 规范应该优先。
(我有具体的例子,也就是说,这实际上是实践中的一个问题,您在最初的评论中已经驳回了这一点)
那么我只能说很抱歉你有这样的服务器。 Werkzeug 对此无能为力。 你展示的片段正是我说“大部分”的原因。 Werkzeug 还包括一个可用于开发的简单测试服务器(例如,避免必须设置 Gunicorn + Nginx/Apache)。 但是,如果您将该服务器暴露在 Internet 上,那么您提到的潜在问题将是您的(安全)问题中最少的。
WSGI 旨在最大程度地与 CGI 兼容。 WSGI 不会覆盖或取代 CGI。 WSGI _is_ CGI。 使 WSGI 应用程序成为有效的 CGI 应用程序所涉及的工作很少。 Python CGI 脚本的os.environ
看起来很像等效的 WSGI 环境。 对此进行任何更改时,需要考虑很多遗留问题。 Werkzeug 作为一个项目在这方面没有发言权,尤其是我。
同样,这个项目的这个问题毫无意义。 Werkzeug 并不是唯一一个有这种行为的人。 由于整个歧义问题,上次我检查 nginx 默认情况下会阻止带有下划线的 HTTP 标头。 大多数其他工具可能只是将它们混为一谈。 如果大多数工具无法区分破折号和下划线,那么标准说有一个就不再重要了。 每个人都被迫一起玩,最终应该归咎于发出带有下划线的标题的工具。
最有用的评论
如果您指的是 PEP 3333,则该行为不是由 WSGI 规范引起的。
PEP 3333 指出:
HTTP_ 变量
对应于客户端提供的 HTTP 请求标头的变量(即名称以“HTTP_”开头的变量)。 这些变量的存在与否应与请求中相应的 HTTP 标头的存在与否相对应。
规范中没有关于以不同方式处理下划线的内容。 事实上,您不符合 PEP 3333 也是因为我不知道哪个标头存在或不存在,即是否存在“App_H”或“App-H”。