7

我正在使用 python 开发一个小型 Web 服务:

  • 烧瓶 (v. 0.8)
  • 风暴 ORM (v. 0.19)
  • 带有 mod_wsgi 的 Apache

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

这是我遇到问题的(为简单起见稍微重写)片段:

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

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

class User(Storm):
    uuid = Unicode(primary=True)
    # Other columns....

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

  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'

我真的不明白为什么会发生这种情况以及我能做些什么。我认为Flask 是 100% unicode

我发现的一个快速解决方法是解码标头值,即uuid = uuid.decode('utf-8'). 这真的是需要做的吗?这似乎有点骇人听闻。有没有办法直接获取unicode,而不必手动“解码”?

4

2 回答 2

14

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

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

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

RequestandResponse类是BaseRequestand 类的子BaseResponse类,并实现 Werkzeug 提供的所有 mixins:

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

headers
来自 WSGI 环境的 headers 是不可变的EnvironHeaders

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

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

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

Headers 主要与 Pythonwsgiref.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).

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

现在让我们开始解码。

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

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

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

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

于 2012-04-12T20:05:30.200 回答
0

标头值是 ASCII,请参阅 Acorn 的链接问题。

您可以在这里做的是像您一样手动解码(尽管您应该使用uuid.decode('ascii')而不是 utf-8)或将您的字段更改RawStrUnicode

于 2012-04-12T16:55:20.117 回答