Flask URL 带有 % 的参数未正确处理
Flask URL Parameters with % Are Not Properly Handled
EDIT2:对于不够清晰,我深表歉意。
我将提供几个值。第一个是我使用前端应用程序调用的 URL。第二个是调用前的值urllib.unquote
。第三个是调用urlib.unquote
.
后的值
前端:
console.log('http://localhost:8080/v1/' + encodeURIComponent(name))
后端:
def f(param=''):
print('*', param)
param = urllib.unquote(param)
print('**', param)
例如
http://localhost:8080/v1/https%3A%2F%2Fgoogle.com
* https:%2F%2Fgoogle.com
** https://google.com
Ex2.
http://localhost:8080/v1/foo%2520bar
* foo%20bar
** foo bar
Ex3.
http://localhost:8080/v1/foo%20bar
* foo bar
** foo bar
感谢您耐心等待并帮助我解决这个问题。我很抱歉在我的原始 post.
中不清楚
编辑:简而言之,如果我调用 /v1/%2520
,参数在函数末尾等于 " "
,而不是函数开头的 "%20"
等于 "%20"
而不是 "%2520"
.
我目前正在使用 Python 2.7.
开发 Flask 应用程序
我正在尝试创建一个可以处理 URL 个参数的函数。
@app.route('/v1/<param>', methods=['DELETE'])
def f(param=''):
param = urllib.unquote(param)
在我的前端应用程序中,我通过对 param
进行编码来调用此函数。但是,如果我将 "foo bar"
和 "foo%20bar"
传递给函数,param
将解析为相同的值——"foo bar"
,而实际上 "foo bar"
应该是 "foo bar"
和 "foo%20bar"
应该是 "foo%20bar"
.
由于这个错误,我无法删除 "foo%20bar"
条目。如果我尝试删除它,它会删除 "foo bar"
,一旦 "foo bar"
被删除,"foo%20bar"
条目将永远不会被删除。
我认为这是因为 "%20"
不等于 "%2520"
,即使那是参数。当我在调用 urllib.unquote(param)
之前打印此值时,它已经等于 "%20"
。然后,当我调用 urllib.unquote(param)
时,值更改为 " "
.
我不确定这是否是 Flask/Werkzeug 中的错误,但它导致我的应用程序无法运行。
你对解决这个问题有什么建议吗?谢谢!
我认为问题是你不理解 URL 编码 :)
它需要避免空格,因此它们会被浏览器转换为 %20 并由 flask 自动返回。
阅读本文以获取更多信息:https://www.w3schools.com/tags/ref_urlencode.asp
解决方案:使用 foo%2520bar
.
将编码的 foo%20bar
发送到服务器
不,Flask 通常处理百分比编码完全正确。 URL 中的参数是百分比编码的,这些是在设置 WSGI 环境时为您解码的。 Flask 然后在匹配时将其传递给您的路线。
您不需要再次解码参数值,移除您的urllib.unquote()
调用。
您的浏览器实际上会为您将 URL 中的 space 编码为 %20
,即使地址栏会显示 space。位置栏对百分比编码的组件进行解码,使其可以读取国际字符(因此 %E3%81%A9%E3%81%86%E3%82%82%E3%81%82%E3%82%8A%E3%81%8C%E3%81%A8%E3%81%86
显示为 どうもありがとう
,例如)。
如果您遇到编码斜线问题(/
、%2F
),请参阅 issue #900,需要考虑 Apache 指令(和其他 WSGI 服务器)的边缘情况.您需要使用 <path:param>
组件来匹配它们,因为默认的 string
参数类型不会匹配斜杠。
如果我使用下面的测试脚本,命名为routetest.py
:
from flask import Flask
try:
from urllib.parse import unquote # PY3
except ImportError:
from urllib import unquote # PY2
app = Flask(__name__)
@app.route('/v1/<path:param>') # NOTE: <path:param> is required to match /
def f(param=''):
return (
f"param: {param}\ndecoded param: {unquote(param)}\n",
200,
{'content-type': 'text/plain'}
)
使用 FLASK_APP=routetest flask run
在 localhost:5000
上启动此脚本,然后我无法重现您的问题:
$ curl http://localhost:5000/v1/https%3A%2F%2Fgoogle.com
param: https://google.com
decoded param: https://google.com
$ curl http://localhost:5000/v1/foo%2520bar
param: foo%20bar
decoded param: foo bar
$ curl http://localhost:5000/v1/foo%20bar
param: foo bar
decoded param: foo bar
这只能表示您有一个 WSGI 服务器在路径中错误处理引用。
EDIT2:对于不够清晰,我深表歉意。
我将提供几个值。第一个是我使用前端应用程序调用的 URL。第二个是调用前的值urllib.unquote
。第三个是调用urlib.unquote
.
前端:
console.log('http://localhost:8080/v1/' + encodeURIComponent(name))
后端:
def f(param=''):
print('*', param)
param = urllib.unquote(param)
print('**', param)
例如
http://localhost:8080/v1/https%3A%2F%2Fgoogle.com
* https:%2F%2Fgoogle.com
** https://google.com
Ex2.
http://localhost:8080/v1/foo%2520bar
* foo%20bar
** foo bar
Ex3.
http://localhost:8080/v1/foo%20bar
* foo bar
** foo bar
感谢您耐心等待并帮助我解决这个问题。我很抱歉在我的原始 post.
中不清楚编辑:简而言之,如果我调用 /v1/%2520
,参数在函数末尾等于 " "
,而不是函数开头的 "%20"
等于 "%20"
而不是 "%2520"
.
我目前正在使用 Python 2.7.
开发 Flask 应用程序我正在尝试创建一个可以处理 URL 个参数的函数。
@app.route('/v1/<param>', methods=['DELETE'])
def f(param=''):
param = urllib.unquote(param)
在我的前端应用程序中,我通过对 param
进行编码来调用此函数。但是,如果我将 "foo bar"
和 "foo%20bar"
传递给函数,param
将解析为相同的值——"foo bar"
,而实际上 "foo bar"
应该是 "foo bar"
和 "foo%20bar"
应该是 "foo%20bar"
.
由于这个错误,我无法删除 "foo%20bar"
条目。如果我尝试删除它,它会删除 "foo bar"
,一旦 "foo bar"
被删除,"foo%20bar"
条目将永远不会被删除。
我认为这是因为 "%20"
不等于 "%2520"
,即使那是参数。当我在调用 urllib.unquote(param)
之前打印此值时,它已经等于 "%20"
。然后,当我调用 urllib.unquote(param)
时,值更改为 " "
.
我不确定这是否是 Flask/Werkzeug 中的错误,但它导致我的应用程序无法运行。
你对解决这个问题有什么建议吗?谢谢!
我认为问题是你不理解 URL 编码 :) 它需要避免空格,因此它们会被浏览器转换为 %20 并由 flask 自动返回。 阅读本文以获取更多信息:https://www.w3schools.com/tags/ref_urlencode.asp
解决方案:使用 foo%2520bar
.
foo%20bar
发送到服务器
不,Flask 通常处理百分比编码完全正确。 URL 中的参数是百分比编码的,这些是在设置 WSGI 环境时为您解码的。 Flask 然后在匹配时将其传递给您的路线。
您不需要再次解码参数值,移除您的urllib.unquote()
调用。
您的浏览器实际上会为您将 URL 中的 space 编码为 %20
,即使地址栏会显示 space。位置栏对百分比编码的组件进行解码,使其可以读取国际字符(因此 %E3%81%A9%E3%81%86%E3%82%82%E3%81%82%E3%82%8A%E3%81%8C%E3%81%A8%E3%81%86
显示为 どうもありがとう
,例如)。
如果您遇到编码斜线问题(/
、%2F
),请参阅 issue #900,需要考虑 Apache 指令(和其他 WSGI 服务器)的边缘情况.您需要使用 <path:param>
组件来匹配它们,因为默认的 string
参数类型不会匹配斜杠。
如果我使用下面的测试脚本,命名为routetest.py
:
from flask import Flask
try:
from urllib.parse import unquote # PY3
except ImportError:
from urllib import unquote # PY2
app = Flask(__name__)
@app.route('/v1/<path:param>') # NOTE: <path:param> is required to match /
def f(param=''):
return (
f"param: {param}\ndecoded param: {unquote(param)}\n",
200,
{'content-type': 'text/plain'}
)
使用 FLASK_APP=routetest flask run
在 localhost:5000
上启动此脚本,然后我无法重现您的问题:
$ curl http://localhost:5000/v1/https%3A%2F%2Fgoogle.com
param: https://google.com
decoded param: https://google.com
$ curl http://localhost:5000/v1/foo%2520bar
param: foo%20bar
decoded param: foo bar
$ curl http://localhost:5000/v1/foo%20bar
param: foo bar
decoded param: foo bar
这只能表示您有一个 WSGI 服务器在路径中错误处理引用。