这是一个应该打印Content-Length的简单WSGI应用程序 和标题中的请求正文。
def application(environ, start_response):
start_response('200 OK', [('Content-Type','text/plain')])
content_length = int(environ['CONTENT_LENGTH'])
print('---- Begin ----')
print('CONTENT_LENGTH:', content_length)
print('wsgi.input:', environ['wsgi.input'].read())
print('---- End ----')
return [b'Foo\n']
if __name__ == '__main__':
from wsgiref import simple_server
server = simple_server.make_server('0.0.0.0', 8080, application)
server.serve_forever()
当我运行此应用程序时,它会在以下调用时被阻止:environ['wsgi.input'].read()
。
我使用Python 3解释器运行应用程序,并使用curl向它提交HTTP post请求。
lone@debian:~$ curl --data "a=1&b=2" http://localhost:8080/
curl命令被阻塞等待输出。 python解释器在environ['wsgi.input'].read()
调用时被阻止。
lone@debian:~$ python3 foo.py
---- Begin ----
CONTENT_LENGTH: 7
正如您在上面的输出中所看到的,application()
功能在打印CONTENT_LENGTH
后被阻止。
我知道如何解决此问题:将Content-Length标头值传递给read()
电话。
修改代码以解决此问题:
def application(environ, start_response):
start_response('200 OK', [('Content-Type','text/plain')])
content_length = int(environ['CONTENT_LENGTH'])
print('---- Begin ----')
print('CONTENT_LENGTH:', content_length)
print('wsgi.input:', environ['wsgi.input'].read(content_length))
print('---- End ----')
return [b'Foo\n']
if __name__ == '__main__':
from wsgiref import simple_server
server = simple_server.make_server('0.0.0.0', 8080, application)
server.serve_forever()
curl命令现在获得有效的HTTP响应。
lone@debian:~$ curl --data "a=1&b=2" http://localhost:8080/
Foo
lone@debian:~$
application()
函数也完成了它的执行。
lone@debian:~$ python3 foo.py
---- Begin ----
CONTENT_LENGTH: 7
wsgi.input: b'a=1&b=2'
---- End ----
127.0.0.1 - - [06/Apr/2014 17:53:21] "POST / HTTP/1.1" 200 4
为什么在没有任何参数的情况下调用environ['wsgi.input'].read()
时read
调用阻塞?
PEP-3333文件似乎暗示它应该有效。这是相关文字。
服务器不需要读取客户端指定的内容
Content-Length
,应该模拟文件结束条件 应用程序试图阅读过这一点。应用程序 不应尝试读取的数据超过CONTENT_LENGTH
变量指定的数据。服务器应该允许在没有参数的情况下调用
read()
, 并返回客户端输入流的其余部分。
我知道应用程序不应该尝试读取比CONTENT_LENGTH
变量指定的数据更多的数据。我不服从这个指令。但是服务器应该允许在没有参数的情况下调用read()
并返回整个输入流。为什么不这样做?
答案 0 :(得分:3)
因为它只实现了PEP 333而不是PEP 3333。
PEP 333没有关于通过返回空字符串来模拟流结束的条件。
在PEP 333中,如果您尝试读取超过CONTENT_LENGTH,如果WSGI服务器支持HTTP 1.1并且正在使用请求管道衬里(保持活动状态),则会出现问题。
我建议你阅读PEP 333并将语言与PEP 3333进行比较。
同时阅读:
我描述了整个问题,因此在为Python 3更新PEP时对PEP的更改做出了贡献。