I have a Flask app to which I need to pass several parameters containing slashes. For example, I have parameter1 = "Clothes/Bottoms"
and parameter2 = "Pants/Jeans"
. I tried doing it this way:
In my HTML/JS:
par1 = encodeURIComponent(parameter1);
par2 = encodeURIComponent(parameter2);
console.log("Par1 = ",par1," par2 = ",par2);
$.ajax({
type:'post',
url:'/get_data'+'/'+par1+'/'+par2,
....
});
and in my app.py
:
@app.route('/get_data/<path:par1>/<path:par2>/',methods=['GET','POST'])
def get_data(par1, par2):
print("In get_data with par1 ",par1," and par2 ",par2)
....
I can see from Javascript print-outs that both parameters look fine after being encoded, but then the Python print out is:
In get_data with par1 Clothes and par2 Bottoms/Pants/Jeans
So it somehow mistakes the slash in par1
's "Clothes/Bottoms"
for part of the URL and shifts "Bottoms"
into par2
.
Is there a better way to handle multiple parameters with slashes than just adding path:
?
With /get_data/<path:par1>/<path:par2>/
, there's no way for Flask to "know" which slash is the separator when it receives a request like /get_data/Clothes/Bottoms/Pants/Jeans/
.
If the number of slashes in par1
is fixed, you could receive the path as a single parameter and then split it into two:
@app.route('/get_data/<path:pars>/')
def get_data(pars):
par1 = '/'.join(pars.split("/",2)[:2]) #par1 is everything up until the 2nd slash
par2 = pars.split("/",2)[2:][0] #par2 is everything after the second slash
Otherwise, you could simply replace the separator slash with another character like:
@app.route('/get_data/<path:par1>-<path:par2>/')
To understand flask (werkzeug) routing. Take aside encoding you used in JavaScript for a second.
Regex pattern used by werkzeug's path
converter is [^/].*?
. This allow any number of /
in url path. Which means only part1 get_data/<path:par1>
can accepts both get_data/Clothes/Bottoms
or get_data/Clothes/Bottoms/Pants/Jeans
.
You are using two path
convertor in part1 and par2 which is bad as one part1 can take all slash.
Now the other issue. why even after encoding url its not working as expected.
Flask uses Werkzeug default WSGI server. And WSGI library unescaped uri before using it for routing. i.e., get_data/Clothes%2FBottoms
gets converted to get_data/Clothes/Bottoms
when it comes to routing.
in your case router receives get_data/Clothes/Bottoms/Pants/Jeans
here it takes is "Clothes" as part1 and rest as part2.
Refer to flask issue regarding this.
Solution
Double escape in JavaScript could be workaround here.
path
converter can also be replaced by string
.
par1 = encodeURIComponent(encodeURIComponent(parameter1));
par2 = encodeURIComponent(encodeURIComponent(parameter2));
$.ajax({
type:'post',
url:'http://localhost:8000/get_data'+'/'+par1+'/'+par2+'/'});
And decode at flask application to get back your strings
from urllib import unquote_plus
@app.route('/get_data/<string:par1>/<string:par2>/',methods=['GET','POST'])
def get_data(par1, par2):
print unquote_plus(par1), unquote_plus(par1)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With