为什么我的 WSGI 应用程序总是在 environ['PATH_INFO'] 中获取 URL 解码路径?

Lon*_*ner 6 python wsgi python-3.x

我有一个简单的裸 WSGI 应用程序:

def application(environ, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    print('PATH_INFO:', environ['PATH_INFO'])
    return [b'<p>Hello World</p>']

if __name__ == '__main__':
    from wsgiref import simple_server
    server = simple_server.make_server('0.0.0.0', 8080, application)
    server.serve_forever()
Run Code Online (Sandbox Code Playgroud)

我提出两个要求:

C:\>curl "http://localhost:8080/<foo>"
<p>Hello World</p>
C:\>curl "http://localhost:8080/%3Cfoo%3E"
<p>Hello World</p>
Run Code Online (Sandbox Code Playgroud)

我得到这个输出:

C:\code>python foo.py
PATH_INFO: /<foo>
127.0.0.1 - - [09/Mar/2014 13:48:39] "GET /<foo> HTTP/1.1" 200 18
PATH_INFO: /<foo>
127.0.0.1 - - [09/Mar/2014 13:48:47] "GET /%3Cfoo%3E HTTP/1.1" 200 18
Run Code Online (Sandbox Code Playgroud)

查看我的应用程序如何获取 URL 解码路径,/<foo>即使在客户端请求时也是如此/%3Cfoo%3E

它表明 wsgiref.simple_server 确保我的应用程序始终获取environ['PATH_INFO'].

但我在 PEP-3333 中找不到记录此行为的任何地方。您能给我指出记录此行为的官方文档吗?

Gra*_*ton 2

如果服务器使其可用,则实际 HTTP 请求行中的 REQUEST_URI 值将是:

REQUEST_URI: '/%3Cfoo%3E'
Run Code Online (Sandbox Code Playgroud)

即使您使用了以下方法,情况也可能是这样:

curl "http://localhost:8080/<foo>"
Run Code Online (Sandbox Code Playgroud)

因为curl 会在发送之前对URL 进行编码以使用% 转义符。

我相信 REQUEST_URI 没有被任何 RFC 涵盖,而是许多服务器提供的变量。但您不能依赖它的存在,因此不要编写依赖于它存在的 WSGI 应用程序。

Web 服务器将在处理 REQUEST_URI 中的 % 转义符之前对其进行解码。因此,最终在 PATH_INFO 中的结果将始终是:

PATH_INFO: '/<foo>'
Run Code Online (Sandbox Code Playgroud)

解码由 WSGI 构建的 CGI 和相关 RFC 涵盖。

参见示例: