It looks like when I'm inside of a pluggable view (MethodView), url_for matching favors the current HTTP method, even though there is a more specific match available on a GET. For example, I want to POST to /foo and, as a result of successfully creating "bar", redirect out of the POST to /foo/bar - which is a valid option for a GET (via a "/foo/<bar>" URL rule) but not a POST. Unfortunately, the result of url_for is /foo?bar=bar, because Flask is determined to only honor POST rules on a POST request. What am I missing? What can I clarify in order to get help with this? Should Flask let me suggest what rules url_for will look at (i.e. add a "_method" parameter to url_for)? Jonathan.
Hi, On 11/2/11 8:46 PM, Jonathan Zempel wrote: > What am I missing? What can I clarify in order to get help with this? > Should Flask let me suggest what rules url_for will look at (i.e. add a > "_method" parameter to url_for)? We originally did not provide that since before MethodViews you could not define the same endpoint to the same method with board tools (ignoring add_url_rule). We since added support for that but forgot to adapt url_for. I just pushed a change that will be in 0.9 which makes it possible to be explicit with _method. Regards, Armin
perfect. This commit gave me the info I needed to do a temporary patch while we wait for 0.9: https://github.com/mitsuhiko/flask/commit/f52e7a9dc944f425c2f2a77706bc2af98b23295c Thanks! On Thu, Nov 3, 2011 at 6:47 PM, Armin Ronacher <armin.ronacher@active-4.com>wrote: > Hi, > > On 11/2/11 8:46 PM, Jonathan Zempel wrote: > > What am I missing? What can I clarify in order to get help with this? > > Should Flask let me suggest what rules url_for will look at (i.e. add a > > "_method" parameter to url_for)? > We originally did not provide that since before MethodViews you could > not define the same endpoint to the same method with board tools > (ignoring add_url_rule). We since added support for that but forgot to > adapt url_for. I just pushed a change that will be in 0.9 which makes > it possible to be explicit with _method. > > > Regards, > Armin >
A bit more color on this one... Here is code that demonstrates the issue: http://paste.pocoo.org/show/501999/ Also, at the moment, this same code is running here - https://lafojano.ep.io/ - on TryFlask, so that if you curl -X POST https://lafojano.ep.io/foo the 302 redirect goes to "/foo?bar=bar". It turns out if you remove the "methods" attribute on line 19, then the redirect goes to "/foo/bar" as expected. Thanks for taking a look, Jonathan. On Wed, Nov 2, 2011 at 12:46 PM, Jonathan Zempel <jzempel@gmail.com> wrote: > It looks like when I'm inside of a pluggable view (MethodView), url_for > matching favors the current HTTP method, even though there is a more > specific match available on a GET. > > For example, I want to POST to /foo and, as a result of successfully > creating "bar", redirect out of the POST to /foo/bar - which is a valid > option for a GET (via a "/foo/<bar>" URL rule) but not a POST. > Unfortunately, the result of url_for is /foo?bar=bar, because Flask is > determined to only honor POST rules on a POST request. > > What am I missing? What can I clarify in order to get help with this? > Should Flask let me suggest what rules url_for will look at (i.e. add a > "_method" parameter to url_for)? > > Jonathan. >
Hey, This is because in your code, the /foo/bar route is specified to take in only GET and PUT, not POST. Add POST to the list to get what you need. On 3 November 2011 03:41, Jonathan Zempel <jzempel@gmail.com> wrote: > A bit more color on this one... Here is code that demonstrates the issue: > > http://paste.pocoo.org/show/501999/ > > Also, at the moment, this same code is running here - > https://lafojano.ep.io/ - on TryFlask, so that if you > > curl -X POST https://lafojano.ep.io/foo > > the 302 redirect goes to "/foo?bar=bar". It turns out if you remove the > "methods" attribute on line 19, then the redirect goes to "/foo/bar" as > expected. > > Thanks for taking a look, > Jonathan. > > On Wed, Nov 2, 2011 at 12:46 PM, Jonathan Zempel <jzempel@gmail.com>wrote: > >> It looks like when I'm inside of a pluggable view (MethodView), url_for >> matching favors the current HTTP method, even though there is a more >> specific match available on a GET. >> >> For example, I want to POST to /foo and, as a result of successfully >> creating "bar", redirect out of the POST to /foo/bar - which is a valid >> option for a GET (via a "/foo/<bar>" URL rule) but not a POST. >> Unfortunately, the result of url_for is /foo?bar=bar, because Flask is >> determined to only honor POST rules on a POST request. >> >> What am I missing? What can I clarify in order to get help with this? >> Should Flask let me suggest what rules url_for will look at (i.e. add a >> "_method" parameter to url_for)? >> >> Jonathan. >> > > -- Regards, Ishbir Singh
Ishbir, Thanks for the reply. But that's not quite right. The redirect at the tail end of the POST processing is effectively producing a GET. In addition, in the scenario I'm modeling here, POST is not a valid HTTP method for /foo/bar. Finally, and most important, if I strip the methods attribute from line 19 (which effectively makes that url rule GET-only by default), then the redirect does indeed produce the desired GET on the /foo/bar path (rather than a GET @ /foo?bar=bar). I think I'm on to a gnarly Flask routing bug, here. Jonathan. On Wed, Nov 2, 2011 at 8:49 PM, Ishbir Singh <webmaster@ishbir.com> wrote: > Hey, > > This is because in your code, the /foo/bar route is specified to take in > only GET and PUT, not POST. Add POST to the list to get what you need. > > > On 3 November 2011 03:41, Jonathan Zempel <jzempel@gmail.com> wrote: > >> A bit more color on this one... Here is code that demonstrates the issue: >> >> http://paste.pocoo.org/show/501999/ >> >> Also, at the moment, this same code is running here - >> https://lafojano.ep.io/ - on TryFlask, so that if you >> >> curl -X POST https://lafojano.ep.io/foo >> >> the 302 redirect goes to "/foo?bar=bar". It turns out if you remove the >> "methods" attribute on line 19, then the redirect goes to "/foo/bar" as >> expected. >> >> Thanks for taking a look, >> Jonathan. >> >> On Wed, Nov 2, 2011 at 12:46 PM, Jonathan Zempel <jzempel@gmail.com>wrote: >> >>> It looks like when I'm inside of a pluggable view (MethodView), url_for >>> matching favors the current HTTP method, even though there is a more >>> specific match available on a GET. >>> >>> For example, I want to POST to /foo and, as a result of successfully >>> creating "bar", redirect out of the POST to /foo/bar - which is a valid >>> option for a GET (via a "/foo/<bar>" URL rule) but not a POST. >>> Unfortunately, the result of url_for is /foo?bar=bar, because Flask is >>> determined to only honor POST rules on a POST request. >>> >>> What am I missing? What can I clarify in order to get help with this? >>> Should Flask let me suggest what rules url_for will look at (i.e. add a >>> "_method" parameter to url_for)? >>> >>> Jonathan. >>> >> >> > > > -- > Regards, > Ishbir Singh > >
Hey, Hmm, now that I look at it, you are right. I guess Armin will tell us more about this issue, I have no clue. On 3 November 2011 09:53, Jonathan Zempel <jzempel@gmail.com> wrote: > Ishbir, > > Thanks for the reply. But that's not quite right. The redirect at the tail > end of the POST processing is effectively producing a GET. In addition, in > the scenario I'm modeling here, POST is not a valid HTTP method for > /foo/bar. Finally, and most important, if I strip the methods attribute > from line 19 (which effectively makes that url rule GET-only by default), > then the redirect does indeed produce the desired GET on the /foo/bar path > (rather than a GET @ /foo?bar=bar). > > I think I'm on to a gnarly Flask routing bug, here. > > Jonathan. > > > On Wed, Nov 2, 2011 at 8:49 PM, Ishbir Singh <webmaster@ishbir.com> wrote: > >> Hey, >> >> This is because in your code, the /foo/bar route is specified to take in >> only GET and PUT, not POST. Add POST to the list to get what you need. >> >> >> On 3 November 2011 03:41, Jonathan Zempel <jzempel@gmail.com> wrote: >> >>> A bit more color on this one... Here is code that demonstrates the issue: >>> >>> http://paste.pocoo.org/show/501999/ >>> >>> Also, at the moment, this same code is running here - >>> https://lafojano.ep.io/ - on TryFlask, so that if you >>> >>> curl -X POST https://lafojano.ep.io/foo >>> >>> the 302 redirect goes to "/foo?bar=bar". It turns out if you remove the >>> "methods" attribute on line 19, then the redirect goes to "/foo/bar" as >>> expected. >>> >>> Thanks for taking a look, >>> Jonathan. >>> >>> On Wed, Nov 2, 2011 at 12:46 PM, Jonathan Zempel <jzempel@gmail.com>wrote: >>> >>>> It looks like when I'm inside of a pluggable view (MethodView), url_for >>>> matching favors the current HTTP method, even though there is a more >>>> specific match available on a GET. >>>> >>>> For example, I want to POST to /foo and, as a result of successfully >>>> creating "bar", redirect out of the POST to /foo/bar - which is a valid >>>> option for a GET (via a "/foo/<bar>" URL rule) but not a POST. >>>> Unfortunately, the result of url_for is /foo?bar=bar, because Flask is >>>> determined to only honor POST rules on a POST request. >>>> >>>> What am I missing? What can I clarify in order to get help with this? >>>> Should Flask let me suggest what rules url_for will look at (i.e. add a >>>> "_method" parameter to url_for)? >>>> >>>> Jonathan. >>>> >>> >>> >> >> >> -- >> Regards, >> Ishbir Singh >> >> > -- Regards, Ishbir Singh
On line 19 if you replace PUT with POST it will work properly. Only has an issue when the route allows PUT. Weird. On Thu, Nov 3, 2011 at 1:00 PM, Ishbir Singh <webmaster@ishbir.com> wrote: > Hey, > Hmm, now that I look at it, you are right. I guess Armin will tell us more > about this issue, I have no clue. > > On 3 November 2011 09:53, Jonathan Zempel <jzempel@gmail.com> wrote: >> >> Ishbir, >> Thanks for the reply. But that's not quite right. The redirect at the tail >> end of the POST processing is effectively producing a GET. In addition, in >> the scenario I'm modeling here, POST is not a valid HTTP method for >> /foo/bar. Finally, and most important, if I strip the methods attribute from >> line 19 (which effectively makes that url rule GET-only by default), then >> the redirect does indeed produce the desired GET on the /foo/bar path >> (rather than a GET @ /foo?bar=bar). >> I think I'm on to a gnarly Flask routing bug, here. >> Jonathan. >> >> On Wed, Nov 2, 2011 at 8:49 PM, Ishbir Singh <webmaster@ishbir.com> wrote: >>> >>> Hey, >>> This is because in your code, the /foo/bar route is specified to take in >>> only GET and PUT, not POST. Add POST to the list to get what you need. >>> >>> On 3 November 2011 03:41, Jonathan Zempel <jzempel@gmail.com> wrote: >>>> >>>> A bit more color on this one... Here is code that demonstrates the >>>> issue: >>>> http://paste.pocoo.org/show/501999/ >>>> Also, at the moment, this same code is running here - >>>> https://lafojano.ep.io/ - on TryFlask, so that if you >>>> curl -X POST https://lafojano.ep.io/foo >>>> the 302 redirect goes to "/foo?bar=bar". It turns out if you remove the >>>> "methods" attribute on line 19, then the redirect goes to "/foo/bar" as >>>> expected. >>>> Thanks for taking a look, >>>> Jonathan. >>>> On Wed, Nov 2, 2011 at 12:46 PM, Jonathan Zempel <jzempel@gmail.com> >>>> wrote: >>>>> >>>>> It looks like when I'm inside of a pluggable view (MethodView), url_for >>>>> matching favors the current HTTP method, even though there is a more >>>>> specific match available on a GET. >>>>> For example, I want to POST to /foo and, as a result of successfully >>>>> creating "bar", redirect out of the POST to /foo/bar - which is a valid >>>>> option for a GET (via a "/foo/<bar>" URL rule) but not a POST. >>>>> Unfortunately, the result of url_for is /foo?bar=bar, because Flask is >>>>> determined to only honor POST rules on a POST request. >>>>> What am I missing? What can I clarify in order to get help with this? >>>>> Should Flask let me suggest what rules url_for will look at (i.e. add a >>>>> "_method" parameter to url_for)? >>>>> Jonathan. >>> >>> >>> >>> -- >>> Regards, >>> Ishbir Singh >> > > > > -- > Regards, > Ishbir Singh >
Adam, Replacing PUT with POST (or just adding POST) does allow it to work. But if you leave just methods=["GET"] on line 19, it also breaks. So the problem isn't with PUT specifically. I'm hoping someone with deeper understanding of the codebase (Armin, et. al.?) can feed me a decent workaround for this issue. I could add "POST" as you've noted, but that's ends up being an unfortunate hack in our app. Jonathan. p.s. pulling up the paste for reference: http://paste.pocoo.org/show/501999/ On Wed, Nov 2, 2011 at 11:25 PM, Adam Patterson <fakeempire@gmail.com>wrote: > On line 19 if you replace PUT with POST it will work properly. Only > has an issue when the route allows PUT. Weird. > > On Thu, Nov 3, 2011 at 1:00 PM, Ishbir Singh <webmaster@ishbir.com> wrote: > > Hey, > > Hmm, now that I look at it, you are right. I guess Armin will tell us > more > > about this issue, I have no clue. > > > > On 3 November 2011 09:53, Jonathan Zempel <jzempel@gmail.com> wrote: > >> > >> Ishbir, > >> Thanks for the reply. But that's not quite right. The redirect at the > tail > >> end of the POST processing is effectively producing a GET. In addition, > in > >> the scenario I'm modeling here, POST is not a valid HTTP method for > >> /foo/bar. Finally, and most important, if I strip the methods attribute > from > >> line 19 (which effectively makes that url rule GET-only by default), > then > >> the redirect does indeed produce the desired GET on the /foo/bar path > >> (rather than a GET @ /foo?bar=bar). > >> I think I'm on to a gnarly Flask routing bug, here. > >> Jonathan. > >> > >> On Wed, Nov 2, 2011 at 8:49 PM, Ishbir Singh <webmaster@ishbir.com> > wrote: > >>> > >>> Hey, > >>> This is because in your code, the /foo/bar route is specified to take > in > >>> only GET and PUT, not POST. Add POST to the list to get what you need. > >>> > >>> On 3 November 2011 03:41, Jonathan Zempel <jzempel@gmail.com> wrote: > >>>> > >>>> A bit more color on this one... Here is code that demonstrates the > >>>> issue: > >>>> http://paste.pocoo.org/show/501999/ > >>>> Also, at the moment, this same code is running here - > >>>> https://lafojano.ep.io/ - on TryFlask, so that if you > >>>> curl -X POST https://lafojano.ep.io/foo > >>>> the 302 redirect goes to "/foo?bar=bar". It turns out if you remove > the > >>>> "methods" attribute on line 19, then the redirect goes to "/foo/bar" > as > >>>> expected. > >>>> Thanks for taking a look, > >>>> Jonathan. > >>>> On Wed, Nov 2, 2011 at 12:46 PM, Jonathan Zempel <jzempel@gmail.com> > >>>> wrote: > >>>>> > >>>>> It looks like when I'm inside of a pluggable view (MethodView), > url_for > >>>>> matching favors the current HTTP method, even though there is a more > >>>>> specific match available on a GET. > >>>>> For example, I want to POST to /foo and, as a result of successfully > >>>>> creating "bar", redirect out of the POST to /foo/bar - which is a > valid > >>>>> option for a GET (via a "/foo/<bar>" URL rule) but not a POST. > >>>>> Unfortunately, the result of url_for is /foo?bar=bar, because Flask > is > >>>>> determined to only honor POST rules on a POST request. > >>>>> What am I missing? What can I clarify in order to get help with this? > >>>>> Should Flask let me suggest what rules url_for will look at (i.e. > add a > >>>>> "_method" parameter to url_for)? > >>>>> Jonathan. > >>> > >>> > >>> > >>> -- > >>> Regards, > >>> Ishbir Singh > >> > > > > > > > > -- > > Regards, > > Ishbir Singh > > >