EDIT2: I apologize for the lack of clarity.
I will provide several values. The first is the URL that I call using my frontend app. The second is the value before calling urllib.unquote
. The third is the value after calling urlib.unquote
.
frontend:
console.log('http://localhost:8080/v1/' + encodeURIComponent(name))
backend:
def f(param=''):
print('*', param)
param = urllib.unquote(param)
print('**', param)
Ex.
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
Thank you for being patient and helping me with this. I apologize for being unclear in my original post.
EDIT: In short, if I call /v1/%2520
, param is equal to " "
at the end of the function, instead of "%20"
, at the beginning of the function it is equal to "%20"
and not "%2520"
.
I'm currently working on a Flask App using Python 2.7.
I'm trying to create a function which can handle URL parameters.
@app.route('/v1/<param>', methods=['DELETE'])
def f(param=''):
param = urllib.unquote(param)
On my frontend application, I call this function by encoding the param
. However, if I pass "foo bar"
and "foo%20bar"
to the function, the param
is resolved to the same value -- "foo bar"
, when really "foo bar"
should be "foo bar"
and "foo%20bar"
should be "foo%20bar"
.
Due to this bug, I am unable to delete the "foo%20bar"
entry. If I try to delete it, it will delete "foo bar"
, and once "foo bar"
is deleted, the "foo%20bar"
entry will never be deleted.
I believe this is because "%20"
is not equal to "%2520"
even though that is what the param is. When I print this value before calling urllib.unquote(param)
it is already equal to "%20"
. Then, when I call urllib.unquote(param)
the value is changed to " "
.
I'm not really sure if this is a bug in Flask/Werkzeug, but it is causing my application to not work.
Do you have any suggestions for fixing this issue? Thanks!
I think the problem is you are not understanding the URL encoding :) It requires to avoid spaces, so they are translated to %20 by the browser and back automatically by flask. Read this for more information: https://www.w3schools.com/tags/ref_urlencode.asp
Solution: send an encoded
foo%20bar
to the server withfoo%2520bar
.No, Flask is usually handling percent encoding exactly right. Parameters in a URL are percent encoded, and these are decoded for you when the WSGI environment is set up. Flask then passes this on to your route when matching.
You do not need to decode the parameter value again, remove your
urllib.unquote()
call.Your browser will actually encode spaces in the URL to
%20
for you, even though the location bar will show a space. The location bar decodes percent-encoded components to make it possible to read international characters (so%E3%81%A9%E3%81%86%E3%82%82%E3%81%82%E3%82%8A%E3%81%8C%E3%81%A8%E3%81%86
is shown asどうもありがとう
, for example).If you are having issues with encoded slashes (
/
,%2F
), then see issue #900, there are edge cases with Apache directives (and other WSGI servers) to consider. You would need to use a<path:param>
component to match those, because the defaultstring
parameter type will not match slashes.If I use the following test script, named
routetest.py
:use
FLASK_APP=routetest flask run
to launch this script onlocalhost:5000
, then I can't reproduce your issues:which can only mean that you have a WSGI server that is mishandling quoting in paths.