首页 > 解决方案 > Flask URL 路由编码问题

问题描述

我在 Flask 中偶然发现了一个奇怪的 Unicode URL 编码问题。

@app.route("/it2/<string:name>")
def render_it2(name=""):
    name = _fix_encoding(name)
    return _render_file("it2", name)

name包含 Unicode 字符时,它们被解码为iso-8859-1 而不是utf-8.

所以我不得不添加这个_fix_encoding功能:

def _fix_encoding(string):
    return string.encode('iso-8859-1').decode('utf8')

我知道这是肮脏的黑客攻击,这就是为什么我想问 Flask/Werkzeug 大师,我的设置有什么问题?为了使 URL 已经以 UTF-8 解码,我应该改变什么,这样就不需要这种丑陋的重新编码了?

SO上有很多类似的问题/答案,但没有真正有用的回答,例如:

我想应该有一些环境变量,或者一些影响默认 Flask 编码的配置选项。

我在该主机上有以下LANG/ :LC_*

$ echo $LANG
en_US.UTF-8

$ export | grep LC
declare -x LC_ADDRESS="en_US.UTF-8"
declare -x LC_IDENTIFICATION="en_US.UTF-8"
declare -x LC_MEASUREMENT="en_US.UTF-8"
declare -x LC_MONETARY="en_US.UTF-8"
declare -x LC_NAME="en_US.UTF-8"
declare -x LC_NUMERIC="en_US.UTF-8"
declare -x LC_PAPER="en_US.UTF-8"
declare -x LC_TELEPHONE="en_US.UTF-8"
declare -x LC_TIME="en_US.UTF-8"

什么都没有iso-8859-1。它从何而来?

标签: pythonpython-3.xflaskunicodewerkzeug

解决方案


哪个应用程序/代码/网页会创建嵌入“名称”的 URL?

它位于“名称”已经是 utf-8 编码的地方生成的 HTTP 标头上,但框架的 HTTP 端被告知它是 latin1。您看不到那么多,因为通常 URL 用“%HH”转义 - 其中“HH”是 UTF-8 序列中的字节。如果可以,请更改 URL 的来源以正确转义它们(在 Python 中,对它的调用将是urllib.parse.quote(url))。

在此处查看从会话 2.1 到 2.5 的官方 URL 规范:https ://www.rfc-editor.org/rfc/rfc3986#section-2.1

显然没有标准的方法来告诉 HTTP 服务器组件(在 Python 端,WSGI 层和 Flask 本身)这是 URL 本身的文本编码 - 这些组件假设为 Latin-1(AKA iso-8859- 1) 对于您的 utf-8 数据使用的 ASCII 集之外的字节。

最后 - 如果在源代码处引用 URL 不是一种选择,那么您的方法就足够了。您可能会更好地保护您的_fix_encoding函数免受格式错误的 utf-8 数据的影响,否则您的应用程序将失败。(只需errors="replace"在调用中添加一个参数即可.decode


推荐阅读