【发布时间】:2018-05-26 07:36:12
【问题描述】:
我编写了一个 Python+WSGI 应用程序,我想在返回最后的 200 和结果正文之前返回一个临时 1xx 状态代码,例如 102“处理中”或 103“早期提示”以及一些标题。
我知道,要在多个步骤中返回数据,我的应用程序需要是可迭代的,例如使用 yield(参见 In WSGI, send response without returning)
但到目前为止我发现的所有示例都只使用一个状态码。我没有办法改变它。比如代码:
import wsgiref, wsgiref.simple_server, time
def app(environ, start):
start('102 Processing', [('Foo', 'bar')])
yield "More to come"
time.sleep(2)
start('200 OK', [('Content-Type', 'text/plain')])
yield "hello, world"
httpd = wsgiref.simple_server.make_server('localhost', 8999, app)
httpd.serve_forever()
只发送 102 状态码,其余发送时崩溃:
Exception happened during processing of request from ('127.0.0.1', 53540)
Traceback (most recent call last):
File "/usr/lib/python2.7/SocketServer.py", line 290, in _handle_request_noblock
self.process_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 318, in process_request
self.finish_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 331, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python2.7/SocketServer.py", line 652, in __init__
self.handle()
File "/usr/lib/python2.7/wsgiref/simple_server.py", line 131, in handle
handler.run(self.server.get_app())
File "/usr/lib/python2.7/wsgiref/handlers.py", line 92, in run
self.close()
File "/usr/lib/python2.7/wsgiref/simple_server.py", line 33, in close
self.status.split(' ',1)[0], self.bytes_sent
AttributeError: 'NoneType' object has no attribute 'split'
----------------------------------------
WSGI 中有没有办法做到这一点?
【问题讨论】:
-
根据我看到的 RFC,这应该是可能的,但我认为您遇到的问题是在标头之后发送响应(文本)然后尝试发送另一个标头。尝试在计时器之前删除第一个“yield”,看看是否可以停止错误。临时标头只允许发送代码 100-199,因此只要您仅在 2xx、3xx、4xx 或 5xx 响应标头之前发送 1xx 代码,您就可以了。至少我是这么读的。
-
@DDeMartini 抱歉,删除第一个收益没有任何改变。
-
该错误是因为“如果 start_response 已被调用,则在没有 exc_info 参数的情况下调用 start_response 是一个致命错误”(python.org/dev/peps/pep-3333/#the-start-response-callable)。我不确定 WSGI 是否支持你想要的。
-
我怀疑这是一个非法操作,但对WSGI不是很熟悉,我不确定。我知道 Perl 和 PHP 都会对已经开始的标头大加抨击,但似乎 RFC 说这应该是可能的......但我们都知道 RFC 并不是关于某些软件如何实现任何东西的最终决定(就像来自 M$ 的历史垃圾,例如 IE)
-
一种解决方法可能是使用此处描述的不推荐使用的方式:stackoverflow.com/a/16775731/6368697 并在此处解释:python.org/dev/peps/pep-0333/#the-write-callable;还确定客户端应用程序正确处理 1XX 标头吗?在(很久)过去,我在那里运气不佳。