使用Flask,我想了解一下wsgi.input参考资料。看一下代码,似乎有不止一种方法可以做到这一点,两者都出现在:
werkzeug.wsgi.get_input_stream(environ, safe_fallback=True):
...
if environ.get('wsgi.input_terminated'):
return stream
...
if content_length is None:
return safe_fallback and _empty_stream or stream
...
令人讨厌的是,我无法弄清楚如何实际发生这些情况(并且他们在文档中几乎没有提及)。
wsgi.input_terminated:我知道我可以设置wsgi环境,如果我使用像Apache这样的合适服务器但我如何在Flask开发服务器下进行,因为Werkzeug在werkzeug中硬编码其wsgi环境。 serving.make_environ()?
safe_fallback:根本无法解决这个问题......如果这个参数只是自己调用并且从未通过,那么这个参数在这里做了什么?我应该如何激活它?
这里很容易遗漏一些东西......
答案 0 :(得分:2)
我知道这是一个非常古老的线程,但我找到了一种方法来处理分块编码请求(我需要流而不是数据)和自定义python应用程序(gunicorn + flask),所以不要使用flask.Flask
作为应用程序我创建了子类:
class FlaskApp(flask.Flask):
def request_context(self, environ):
# it's the only way I've found to handle chunked encoding request (otherwise flask.request.stream is empty)
environ['wsgi.input_terminated'] = 1
return super(FlaskApp, self).request_context(environ)
任何人都更好地了解如何以更好的方式做到这一点?
答案 1 :(得分:2)
这是@javabrett函数在他对@ddzialek的答案中的建议中稍微复杂一点的版本。这个在设置标志之前检查分块输入(我不是肯定的,但是设置你可能不需要的标志似乎不是一个好主意。)
@app.before_request
def handle_chunking():
"""
Sets the "wsgi.input_terminated" environment flag, thus enabling
Werkzeug to pass chunked requests as streams; this makes the API
compliant with the HTTP/1.1 standard. The gunicorn server should set
the flag, but this feature has not been implemented.
"""
transfer_encoding = request.headers.get("Transfer-Encoding", None)
if transfer_encoding == "chunked":
request.environ["wsgi.input_terminated"] = True
实际出现的“Transfer-Encoding”的值可能是Unicode而不是ASCII,因此“u'chunked”会更准确 - 但对于ASCII范围内的字符,差异无关紧要( Python将以任何方式匹配字符串),而Python 3不需要“u”。
编辑:重要的是要注意一些WSGI服务器不再需要此修复程序。但是,gunicorn
确实如此(希望问题是fixed soon,但目前Flask
代码需要上述修复。)
答案 2 :(得分:1)
@ddzialak发布的解决方案很有效,但是使用request.stream.read(chunk_size)或request.get_data()读取流会提供完整的流内容,包括标题。以下是我用来获取他们使用的信息的工具:
str_data = request.get_data() # stream data
pattern = re.compile(r'\r\n\r\n(.+?)\n\r\n', flags=re.DOTALL) # content regex
file_data = pattern.findall( str_data.decode('UTF-8') )[0] # what my tools use