【问题标题】:Flask - headers are not converted to unicode?Flask - 标头未转换为 unicode?
【发布时间】:2012-04-12 13:40:29
【问题描述】:

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

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

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

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

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 was 100% unicode

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

【问题讨论】:

标签: python unicode flask werkzeug storm-orm


【解决方案1】:

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

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

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

RequestResponse 类是 BaseRequestBaseResponse 类并实现 Werkzeug 提供的所有 mixins:

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

标题
来自 WSGI 环境的标头是不可变的 EnvironHeaders

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

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

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

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/,其中没有明确定义标题应该是什么类型,但是在搜索单词headers一段时间后,我们找到了这个语句

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 中你得到的标题是 str 而不是 unicode

现在让我们开始解码。

您的.decode('utf-8') 和mensi 的.decode('ascii')(也不是盲目地期待任何其他编码)都不是普遍适用的,因为In theory, HTTP header field values can transport anything; the tricky part is to get all parties (sender, receiver, and intermediates) to agree on the encoding.。说了这么多,我觉得你应该按照 Julian Reshke 的advice

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

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

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

【讨论】:

    【解决方案2】:

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

    你可以在这里做的或者像你一样手动解码(虽然你应该使用uuid.decode('ascii')而不是utf-8)或者将你的字段更改为RawStr而不是Unicode

    【讨论】:

    • 感谢您提及RawStr。在我的具体情况下,这确实是一个更好的选择。
    猜你喜欢
    • 1970-01-01
    • 2012-11-07
    • 1970-01-01
    • 1970-01-01
    • 2020-08-28
    • 1970-01-01
    • 2011-06-12
    • 2017-06-20
    • 2020-06-21
    相关资源
    最近更新 更多