every now and then i use Flask to get some REST service up and running in no time. recently i had an interesting case, as API i exposed was in a form /api/1/branch/<brn>/stuff
, where brn
was a VCS branch name, that the API referred to. after some time, one of the project teams started to send out their branches data. branches however were in the form feature/foo-bar
… and boom – API returned an error, that path does not exist. so the obvious solution was to URL-encode it, i.e. feature%2Ffoo-bar
… and the same! it turned out that Flask is kind enough to parse URL-encoded data for you. convenient. unless it is not sth that you want… :/
the answer is “parameter types”. when you normally type in route in flask, it looks like this:
@app.route("/api/1/branch/<brn>/stuff") def handle_stuff(brn): foobar(brn)
you are implicitly getting string
parameter type. this is where (and why) Flask URL-decides %2F
into /
.
there are however other types, like int
and path
. in particular path
can handle %2F
properly. so the “correct” code is:
@app.route("/api/1/branch/<path:brn>/stuff") def handle_stuff(brn): foobar(brn)
now users can send out feature%2Ffoo-bar
and a proper function will get called, with brn
set to feature/foo-bar
, as expected.
it took me a bit of searching. the main problem was that i was looking for ways to “disable URL-encoding in flask” (and similar) and there i got bunch of “can't do”, “won't work” and rally nasty hacks in the implementation of a backend. in the end, the solution turned out to be trivial… once you know what are you looking for. it would be nice if it was more explicit in a documentation (FAQ maybe?).