这是一个简单的WSGI应用程序,应该可以打印Content-Length
以及标头中的请求正文.
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发布请求.
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
从上面的输出中可以看到,在打印CONTENT_LENGTH之后,application()函数被阻塞了.
解决方法
我知道如何解决该问题:通过将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
题
为什么在不带任何参数的情况下调用read时,environ [‘wsgi.input’].read()调用块为何?
PEP-3333文档似乎暗示它应该可以工作.这是相关的文本.
The server is not required to read past the client’s specified
Content-Length
, and should simulate an end-of-file condition if
the application attempts to read past that point. The application
should not attempt to read more data than is specified by theCONTENT_LENGTH
variable.A server should allow
read()
to be called without an argument,
and return the remainder of the client’s input stream.
我了解,应用程序不应尝试读取超过CONTENT_LENGTH变量指定的更多数据.我不遵守该指令.但是服务器应允许在不带参数的情况下调用read(),并向我返回整个输入流.为什么不这样做呢?
PEP 333没有通过返回空字符串来模拟流的结尾的条件.
在PEP 333中,如果WSGI服务器支持HTTP 1.1并且正在使用请求管道衬里(保持活动状态),并且尝试读取的内容超过CONTENT_LENGTH,则可能会遇到问题.
我建议您阅读PEP 333并将该语言与PEP 3333进行比较.
另请阅读:
> http://blog.dscpl.com.au/2009/10/details-on-wsgi-10-amendmentsclarificat.html
我在其中描述了整个问题,因此在为Python 3更新PEP时做出了贡献.
相关文章
转载注明原文:python-为什么environ [‘wsgi.input’].read()会阻塞,即使PEP-3333允许也是如此? - 代码日志