我正在使用带有FCGI的Python Flask + nginx。
在某些请求中,我必须输出大量响应。通常这些响应是从套接字中获取的。目前我正在做这样的回复:
response = []
while True:
recv = s.recv(1024)
if not recv: break
response.append(recv)
s.close()
response = ''.join(response)
return flask.make_response(response, 200, {
'Content-type': 'binary/octet-stream',
'Content-length': len(response),
'Content-transfer-encoding': 'binary',
})
问题是我实际上不需要数据。我还有办法确定从套接字中提取的确切响应长度。所以我需要一个很好的方法来发送HTTP头,然后直接从套接字开始输出,而不是在内存中收集它然后提供给nginx(可能通过某种流)。
我无法找到这个看似常见问题的解决方案。如何实现?
谢谢!
答案 0 :(得分:10)
如果response
中的flask.make_response
是可迭代的,它将被迭代以产生响应,并且每个字符串都会自己写入输出流。
这意味着您还可以返回一个生成器,它将在迭代时产生输出。如果您知道内容长度,那么您可以(并且应该)将其作为标题传递。
一个简单的例子:
from flask import Flask
app = Flask(__name__)
import sys
import time
import flask
@app.route('/')
def generated_response_example():
n = 20
def response_generator():
for i in range(n):
print >>sys.stderr, i
yield "%03d\n" % i
time.sleep(.2)
print >>sys.stderr, "returning generator..."
gen = response_generator()
# the call to flask.make_response is not really needed as it happens imlicitly
# if you return a tuple.
return flask.make_response(gen ,"200 OK", {'Content-length': 4*n})
if __name__ == '__main__':
app.run()
如果你运行它并在浏览器中尝试它,你应该看到一个很好的实际计数......
(内容类型未设置,因为看起来如果我这样做,我的浏览器会等到整个内容在呈现页面之前流式传输。wget -qO - localhost:5000
没有这个问题。