带有%的Flask URL参数处理不正确

时间:2019-03-19 17:04:17

标签: python url flask encoding werkzeug

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

感谢您耐心等待并为我提供帮助。抱歉,我在原始帖子中不清楚。

编辑:简而言之,如果我调用/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"应该是{ {1}}和"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中的错误,但这会导致我的应用程序无法正常工作。

您对解决此问题有任何建议吗?谢谢!

2 个答案:

答案 0 :(得分:1)

不,Flask通常会处理完全正确的百分比编码 。 URL中的参数是百分比编码的,并且在设置WSGI环境时会为您解码这些参数。匹配后,Flask会将其传递到您的路线。

不需要,无需再次解码参数值,删除您的urllib.unquote()调用。

即使位置栏将显示一个空格,您的浏览器实际上也会为您在%20的URL中编码空格。位置栏对百分比编码的组件进行解码,以使其可以读取国际字符(例如,%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: {urllib.parse.unquote(param)}\n",
        200,
        {'content-type': 'text/plain'}
    )

使用FLASK_APP=routetest flask runlocalhost: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服务器。

答案 1 :(得分:0)

我认为问题是您不了解URL编码:) 它需要避免空格,因此它们会被浏览器转换为%20,并被flask自动返回。 请阅读以下内容以获取更多信息:https://www.w3schools.com/tags/ref_urlencode.asp

解决方案:使用foo%20bar将编码的foo%2520bar发送到服务器。