【问题标题】:Flask URL route encoding problemsFlask URL 路由编码问题
【发布时间】:2021-02-11 00:50:55
【问题描述】:

我偶然发现了一个奇怪的 Unicode Flask 中的 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。它来自哪里?

【问题讨论】:

  • 生成 URL 中使用的“名称”的代码在哪里?就这部分代码而言,“名称”只是一个输入:它是在其他地方使用不正确的编码创建的。
  • @jsbueno 我真的不明白你的问题。你的意思是什么代码?它是一个单行的 Flask 应用程序; import Flask还有这个函数,就是整个代码

标签: python python-3.x flask unicode werkzeug


【解决方案1】:

哪个应用程序/代码/网页会创建嵌入“名称”的 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 数据的影响,否则您的应用程序将失败。 (只需在对.decode 的调用中添加errors="replace" 参数即可)

【讨论】:

  • 谢谢你的回答,简而言之就是:“没关系,忍受它”。至少从这个角度来看是有帮助的,我不觉得自己太傻了,因为我错过了一些明显的东西。但我仍然希望,必须有一些真正的解决方案。至少,它之前工作正常(基于python 2.x)。在现实生活中,无论如何都会有一个 Web 前端服务器,它可以根据需要对 URL 进行编码,但我想知道如何配置 Flask,以便它自己正确处理 URL
  • Python 2.x 的不同之处在于 Flask 将处理视图字节串:您的视图将选择如何解码它。现在,Flask 为您处理一个文本字符串:它必须首先对其进行解码 - 但规范中没有办法声明 URL 的编码并且 Flask + WSGI 假定为 latin-1。这种编码的优点是“无损”:URL 中的所有字节都会变成 0-256 范围内的 unicode 字符。做你所做的可以将它改回正确的编码。也许有一些配置可以更改为烧瓶以字节形式提供 url 而不是尝试对其进行解码
  • 是的,我同意配置,实际上这是我最初的问题
猜你喜欢
  • 2018-05-07
  • 2016-05-14
  • 2010-11-14
  • 2017-03-26
  • 2017-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多