我已经在 docker 中从
nvidia/cuda:12.5.1-cudnn-runtime-ubuntu22.04
构建了一个 Flask 应用程序。但是这个flask无法接收任何
utf-8
请求,并出现
Bad request syntax
错误。
# here the messy code ä½\xa0好 is 你好 in Chinese, which means hello
code 400, message Bad request syntax ('GET /chat?question=ä½\xa0好 HTTP/1.1')
对于查询的英文字符
question=hello
,一切正常。我尝试设置
app.json.ensure_ascii = False
并在curl中设置
charset=UTF-8
,但得到了同样的错误。
但是,当我使用
gunicorn
启动应用程序时,它可以工作。顺便说一句,我将docker镜像的语言环境设置为中文,所以可能不是系统问题。
这是
test.py
的演示代码:
from flask import Flask, request
from loguru import logger
app = Flask(__name__)
app.json.ensure_ascii = False
@app.route("/chat", methods=["GET"])
def chat():
query = request.args.get("question")
logger.info(f"用户提问: {query}", enqueue=True)
print(query)
return query
@app.route("/")
def test():
return "你好"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=10132, debug=True)
我用
python test.py
运行这个演示片段。
curl
的请求很简单
curl --request GET 'http://172.18.0.3:10132/chat?question=你好
然后我收到此错误:
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error response</title>
</head>
<body>
<h1>Error response</h1>
<p>Error code: 400</p>
<p>Message: Bad request syntax ('GET /chat?question=ä½\xa0好 HTTP/1.1').</p>
<p>Error code explanation: 400 - Bad request syntax or unsupported method.</p>
</body>
</html>
其他可能有用的信息:
# OS Which is followed the container nvidia/cuda:12.5.1-cudnn-runtime-ubuntu22.04
PRETTY_NAME="Ubuntu 22.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.4 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
# Flask version, it is installed through conda
flask 3.0.3 pyhd8ed1ab_0 conda-forge
# Python version
python 3.11.9 hb806964_0_cpython conda-forge
问题在于的终端和 Flask 应用程序之间传递 URL 编码的中文参数时出现了问题。
解决方法:
-
URL 编码:
确保的中文参数在发送到 Flask 应用程序之前已正确进行 URL 编码。可以使用 Python 的
urllib.parse.quote
函数对中文进行编码。
import urllib.parse
chinese_text = "你好"
encoded_text = urllib.parse.quote(chinese_text)
print(encoded_text) # 输出:%E4%BD%A0%E5%A5%BD
-
URL 解码:
在 Flask 应用程序中,使用
urllib.parse.unquote
函数对接收到的编码参数进行解码。
from flask import Flask, request
import urllib.parse
app = Flask(__name__)
@app.route("/chat", methods=["GET"])
def chat():
query = request.args.get("question")
decoded_query = urllib.parse.unquote(query)
# ...
return decoded_query
# ...
修改后的 curl 命令:
curl --request GET 'http://172.18.0.3:10132/chat?question=%E4%BD%A0%E5%A5%BD'
完整示例:
test.py
from flask import Flask, request
import urllib.parse
app = Flask(__name__)
app.json.ensure_ascii = False
@app.route("/chat", methods=["GET"])
def chat():
query = request.args.get("question")
decoded_query = urllib.parse.unquote(query)
print(f"用户提问: {decoded_query}")
return decoded_query
@app.route("/")
def test():
return "你好"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=10132, debug=True)
运行并测试:
-
运行
python test.py
启动 Flask 应用程序。 - 在终端中执行以下命令:
curl --request GET 'http://172.18.0.3:10132/chat?question=%E4%BD%A0%E5%A5%BD'
应该会在终端中看到 "用户提问: 你好" 的输出,并且 Flask 应用程序将返回 "你好"。
注意:
- 确保的终端和 Flask 应用程序使用相同的字符编码 (UTF-8)。
-
使用
urllib.parse
模块进行 URL 编码和解码可以确保跨平台兼容性。