Flask - 标题未转换为unicode?

lum*_*lum 7 python unicode werkzeug flask storm-orm

我正在使用以下方法在python中开发一个小型Web服务:

  • 烧瓶(v.8.8)
  • 风暴ORM(v.0.19)
  • Apache与mod_wsgi

我有一个自定义HTTP标头,Unison-UUID我正在使用它来检索我的数据库中的信息.

这是(稍为简单的重写)片段,我遇到了麻烦:

uuid = flask.request.headers['Unison-UUID']
store = storm.locals.Store(my_database)
user = store.get(models.User, uuid)
Run Code Online (Sandbox Code Playgroud)

这个班User或多或少是这样的:

class User(Storm):
    uuid = Unicode(primary=True)
    # Other columns....
Run Code Online (Sandbox Code Playgroud)

上面的代码以下列方式失败:

  File "/Users/lum/Documents/unison-recsys/www/api/unison/unison.py", line 27, in decorated
    user = g.store.get(models.User, uuid)
  File "/Users/lum/Documents/unison-recsys/venv/lib/python2.6/site-packages/storm/store.py", line 165, in get
    variable = column.variable_factory(value=variable)
  File "/Users/lum/Documents/unison-recsys/venv/lib/python2.6/site-packages/storm/variables.py", line 396, in parse_set
    % (type(value), value))
TypeError: Expected unicode, found <type 'str'>: '00000000-0000-0000-0000-000000000009'
Run Code Online (Sandbox Code Playgroud)

我真的不明白为什么会这样,我能做些什么呢.我认为Flask是100%unicode.

我找到的快速修复方法是解码标头值,即uuid = uuid.decode('utf-8').这真的需要做什么?这看起来有点骇人听闻.有没有办法直接获得unicode,而无需手动"解码"?

Pio*_*ost 13

http://flask.pocoo.org/docs/api/#flask.request上我们读了

请求对象是Request子类的实例,并提供Werkzeug定义的所有属性.

这个词Request链接到http://werkzeug.pocoo.org/docs/wrappers/#werkzeug.wrappers.Request我们读到的地方

RequestResponse类的子类BaseRequestBaseResponse类和实现所有WERKZEUG提供混入:

这个词BaseRequest链接到http://werkzeug.pocoo.org/docs/wrappers/#werkzeug.wrappers.BaseRequest我们读到的地方

headers
WSGI环境中的头文件是不可变的EnvironHeaders.

这个词EnvironHeaders链接到我们阅读的http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.EnvironHeaders

这提供了与Headers相同的接口,并且是从WSGI环境构建的.

标题这个词是......不,它没有链接,但应该链接到http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.Headers我们在哪里阅读

标头大多与Python wsgiref.headers.Headers类兼容

这句话wsgiref.headers.Headers链接到http://docs.python.org/dev/library/wsgiref.html#wsgiref.headers.Headers我们在哪里阅读

创建一个类似映射的对象包装头,它必须是头名称/值元组的列表,如中所述PEP 3333.

这个短语PEP 3333链接到http://www.python.org/dev/peps/pep-3333/,其中没有明确定义标题应该是什么类型但是在搜索单词标题一段时间后我们发现此语句

因此,WSGI定义了两种"字符串":

"Native" strings (which are always implemented using the type named str)
that are used for request/response headers and metadata
"Bytestrings" (which are implemented using the `bytes` type in Python 3,
and `str` elsewhere), that are used for the bodies of requests and
responses (e.g. POST/PUT input data and HTML page outputs).
Run Code Online (Sandbox Code Playgroud)

这就是为什么在Python 2中你得到的标题str不是unicode.

现在让我们转向解码.

既不是你的.decode('utf-8')也不是meni .decode('ascii')(也不是盲目地期望任何其他编码)是普遍好的,因为理论上,HTTP头字段值可以传输任何东西; 棘手的部分是让所有各方(发送者,接收者和中间人)就编码达成一致..话虽如此,我认为你应该按照Julian Reshke的建议行事

因此,执行此操作的安全方法是坚持使用ASCII,并在其上选择一种编码,例如RFC 5987中定义的编码.

在检查您支持的用户代理(浏览器)是否已实现它之后.

RFC 5987的标题是用于超文本传输​​协议(HTTP)报头字段参数的字符集和语言编码

  • 非常详细的回答,非常感谢! (2认同)