在包含unicode_literals的Flask应用程序中添加标题

添加启用了unicode_literals的头文件似乎失败了Nginx,uWSGI和一个简单的Flask应用程序:

# -*- coding: utf-8 -*- from __future__ import unicode_literals from flask import Flask, make_response app = Flask('test') @app.route('/') def index(): response = make_response() response.status_code = 401 response.headers = {'WWW-Authenticate': 'Basic realm="test"'} # Fail # response.headers = {b'WWW-Authenticate': b'Basic realm="test"'} # Succeed return response if __name__ == '__main__': app.run(debug=True) 

该应用程序可直接用于debugging目的,或通过Nginx – > uWSGI – > Flask,并运行良好。

  • 当我使用浏览器直接连接到应用程序时,我有一个login对话框, WWW-Authenticate标头是正确的。
  • 通过Nginx的相同请求返回一个头部Transfert-Encoding: chunked并丢弃WWW-Authenticate头部。

强制使用string( b'...') format to add the header make the app works as expected in both cases. The file is encoded in UTF-8 and there's a b'...') format to add the header make the app works as expected in both cases. The file is encoded in UTF-8 and there's a Python解释器b'...') format to add the header make the app works as expected in both cases. The file is encoded in UTF-8 and there's a编码声明。 我们使用Python 2.7.3,Nginx 1.4.2和uWSGI 1.3。

Nginx或uWSGI,Flask和unicode_literals之间是否有任何已知的不兼容? 谢谢!

编辑:这个问题似乎来自uWSGI( https://github.com/unbit/uwsgi/blob/master/plugins/python/wsgi_headers.c#L116 ),因为它只检查PyString而不是Python2的PyUnicode,如果我正确理解这个代码。

编辑:Armin Ronacher已经修复了一个类似的错误( https://github.com/mitsuhiko/flask/issues/758)5个月前,但我没有find提交werkzeug git日志呢。 我不知道这个修补程序的作用范围是redirect()函数还是更广泛地处理了头文件。 我使用的是Werkzeug 0.9.4和Flask 0.10.1。

这个问题确实是由于Werkzeug中的一个错误造成的。 正如您注意到的那样,现在已经从2013年6月4日起更正了(参见Github上的相关提交 )。 你可以通过使用版本0.9.5而不是0.9.4来获得一个无错误版本的Werkzeug。

而且,为了解决你的问题,我在Flask应用程序的初始化之后添加了app.debug = True 。 这使我在uWSGI日志中得到以下错误:

 Traceback (most recent call last): File "/home/afigura/.virtualenvs/stack-python2/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__ return self.wsgi_app(environ, start_response) File "/home/afigura/.virtualenvs/stack-python2/lib/python2.7/site-packages/flask/app.py", line 1821, in wsgi_app return response(environ, start_response) File "/home/afigura/.virtualenvs/stack-python2/lib/python2.7/site-packages/werkzeug/wrappers.py", line 1201, in __call__ start_response(status, headers) TypeError: http header key must be a string 

这对应于您在Github上发现的错误中提到的错误 。

因此,您可以使用以下解决方法来让Flask / Werkzeug使用unicode_literals

 response.headers = {b'WWW-Authenticate': 'Basic realm="test"'} 

要么:

 response.headers = {str('WWW-Authenticate'): 'Basic realm="test"'} 

但是,如果可以的话,我建议只更新你的Werkzeug版本到> = 0.9.5。

另外,请注意,虽然Flask / Werkzeug响应的headers属性像字典一样,但实际上它是一个Headers对象(请参阅Werkzeug源代码 )。 因此,我建议你使用它如下:

 response.headers['WWW-Authenticate'] = 'Basic realm="test"' 

你可以在make_response函数的Flask文档中看到这方面的一些例子。