Skip Menu |

This queue is for tickets about the Catalyst-Plugin-RequireSSL CPAN distribution.

Report information
The Basics
Id: 38996
Status: open
Priority: 0/
Queue: Catalyst-Plugin-RequireSSL

People
Owner: Nobody in particular
Requestors: norbi [...] nix.hu
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: code duplication: $c->uri_for() is reimplemented in RequireSSL.pm
Date: Thu, 4 Sep 2008 20:13:24 +0200
To: bug-Catalyst-Plugin-RequireSSL [...] rt.cpan.org
From: BUCHMULLER Norbert <norbi [...] nix.hu>
It seems that for some reason the code that recreates the path part of the URL (from the controller, action, arguments and query parameters) is reimplemented from scratch in Catalyst::Plugin::RequireSSL::_redirect_uri(). This is unfortunate not only because it is code duplication (this functionality is already present in Catalyst::uri_for()), but as this code path does not use $c->uri_for(), the user-defined uri_for() hooks are are ignored when constructing the URL. For example, our webapp stores the interface language code as a prefix to the path part of the URL (eg. http://example.com/en/some/page). It strips the language code off in a prepare_path() hook (and saves its value in the stash), thus the Catalyst dispatcher does not see it (and the controllers layout is not affected by it). Finally in an uri_for() hook the language prefix is prepended back to the URL path, so the URLs will have the language code prefix again. In this scenario RequireSSL.pm breaks the application, as it bypasses the uri_for() hook (and the language code will be missing from the URL). See the attached patch for an implementation that uses uri_for(). norbi

Message body is not shown because sender requested not to inline it.

Subject: Re: [rt.cpan.org #38996] code duplication: $c->uri_for() is reimplemented in RequireSSL.pm
Date: Wed, 10 Sep 2008 18:11:47 +0100
To: BUCHMULLER Norbert via RT <bug-Catalyst-Plugin-RequireSSL [...] rt.cpan.org>
From: Matt S Trout <mst [...] shadowcat.co.uk>
On Thu, Sep 04, 2008 at 02:14:03PM -0400, BUCHMULLER Norbert via RT wrote: Show quoted text
> Thu Sep 04 14:14:00 2008: Request 38996 was acted upon. > Transaction: Ticket created by norbi@nix.hu > Queue: Catalyst-Plugin-RequireSSL > Subject: code duplication: $c->uri_for() is reimplemented in RequireSSL.pm > Broken in: (no value) > Severity: (no value) > Owner: Nobody > Requestors: norbi@nix.hu > Status: new > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=38996 > > > > It seems that for some reason the code that recreates the path part of > the URL (from the controller, action, arguments and query parameters) is > reimplemented from scratch in > Catalyst::Plugin::RequireSSL::_redirect_uri(). > > This is unfortunate not only because it is code duplication (this > functionality is already present in Catalyst::uri_for()), but as this > code path does not use $c->uri_for(), the user-defined uri_for() hooks > are are ignored when constructing the URL. > > For example, our webapp stores the interface language code as a prefix to > the path part of the URL (eg. http://example.com/en/some/page). It strips > the language code off in a prepare_path() hook (and saves its value in > the stash), thus the Catalyst dispatcher does not see it (and the > controllers layout is not affected by it). Finally in an uri_for() hook > the language prefix is prepended back to the URL path, so the URLs will > have the language code prefix again. In this scenario RequireSSL.pm > breaks the application, as it bypasses the uri_for() hook (and the > language code will be missing from the URL). > > See the attached patch for an implementation that uses uri_for().
Your patch doesn't include captures and won't work for complex regexp actions even if it did. However, if you were to supply a patch -with tests- that simply did $c->uri_for('/'.$c->req->path,$c->req->query_parameters) I think -that- would work in all cases and work around your problem. A better solution for -you- IMO would be if you captured the language via a sub lang :Chained('/') :CaptureArgs(1) { action - then this would all work already; mangling $c->req->path is dangerous and highly inadvisable. -- Matt S Trout Need help with your Catalyst or DBIx::Class project? Technical Director http://www.shadowcat.co.uk/catalyst/ Shadowcat Systems Ltd. Want a managed development or deployment platform? http://chainsawblues.vox.com/ http://www.shadowcat.co.uk/servers/
Subject: Re: [rt.cpan.org #38996] code duplication: $c->uri_for() is reimplemented in RequireSSL.pm
Date: Thu, 18 Sep 2008 00:25:21 +0200
To: bug-Catalyst-Plugin-RequireSSL [...] rt.cpan.org
From: BUCHMULLER Norbert <norbi [...] nix.hu>
On Wed, 10 Sep 2008 13:12:10 -0400 "Matt S Trout via RT" <bug-Catalyst-Plugin-RequireSSL@rt.cpan.org> wrote: Show quoted text
> Your patch doesn't include captures and won't work for complex regexp > actions even if it did. However, if you were to supply a patch -with > tests- that simply did > $c->uri_for('/'.$c->req->path,$c->req->query_parameters) I think -that- > would work in all cases and work around your problem.
You're right, I did not take the captures into account. OTOH $c->req->path does not necessarily correspond to the path argument of $c->uri_for() (that's exactly the reason why we have $c->uri_for(), isn't it?:-). What do you think of this solution: $c->uri_for( $c->action, $c->req->captures, @{$c->req->arguments}, $c->req->params ); According the documentation of Catalyst::uri_for(), if $path is an action object and the first argument after it is an array ref, it is considered as the list of captures, and is passed to $c->dispatcher->uri_for_action() along with the action object. So, if the dispatcher can reconstruct the path from the action object and the captures, it works. Now the question is how much can we depend on it (ie. that uri_for_action() works well). For Catalyst::DispatchType::Regex I just filed a bug report (rt.cpan.org #39369), as its uri_for_action() is totally broken. But even if my patch is accepted, the implementation is still admittedly weak (eg. it cannot cope with nested parentheses according to the documentation), and it's no surprise, as the task is inherently very tough (to reconstruct the original string that was matched from the regex and captures). So, it's still not clear for me if it's worth to try to push the $c->action plus $c->req->captures version in favour of the $c->req->path version.. it gives more freedom in the (mis)use of $c->uri_for(), at the price of depending on shaky uri_for_action() implementations. Not that it would be my role to decide in this question. ;-) Can you please check the attached patch? (Even if you'd reject the $c->action + $c->req->captures solution; in that case pls review it only for the style and some general issues regarding the tests.) I created a test case for a Regex action, and a test case for a scenario where the user mangles $c->req->path from prepare_path() and uri_for(). (I plan to create a test case for a Chained action, too.) An implementation detail, to explain some changes: I ran into an issue after switching to using uri_for(): the order of the query parameters in the URI created by uri_for() is randomly shuffled. (For Catalyst the order does not matter - you can only access the query parameters in a hash ref; so in uri_for() it uses the order in which Perl returns the hash keys.) As in text comparison or using the comparison function of the URI module the order of query parameters is significant, I klugded all URI comparisons by wrapping the URI returned from Catalyst in a function (URI::UnorderedQueryParams::uri()) that returns an URI object with the query params in lexicographic order. If you know anything better/cleaner, pls tell me. Show quoted text
> A better solution for -you- IMO would be if you captured the language > via a > > sub lang :Chained('/') :CaptureArgs(1) { > > action - then this would all work already; mangling $c->req->path is > dangerous and highly inadvisable.
Thanks for pointing it out. In fact I perused the manual of Catalyst::DispatchType::Chained twice before we settled with the prepare_path() + uri_for() hack, as I felt that it's something very close, but somehow it did not lend itself as the solution we looked for. It did not get through for me that there need not be one predetermined endpoint for each chain. I'll convert our app to use Chained soon. Best regards, norbi

Message body is not shown because sender requested not to inline it.

CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #38996] code duplication: $c->uri_for() is reimplemented in RequireSSL.pm
Date: Wed, 24 Sep 2008 16:23:26 +0100
To: BUCHMULLER Norbert via RT <bug-Catalyst-Plugin-RequireSSL [...] rt.cpan.org>
From: Matt S Trout <mst [...] shadowcat.co.uk>
On Wed, Sep 17, 2008 at 06:26:07PM -0400, BUCHMULLER Norbert via RT wrote: Show quoted text
> Queue: Catalyst-Plugin-RequireSSL > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=38996 > > > On Wed, 10 Sep 2008 13:12:10 -0400 "Matt S Trout via RT" > <bug-Catalyst-Plugin-RequireSSL@rt.cpan.org> wrote: >
> > Your patch doesn't include captures and won't work for complex regexp > > actions even if it did. However, if you were to supply a patch -with > > tests- that simply did > > $c->uri_for('/'.$c->req->path,$c->req->query_parameters) I think -that- > > would work in all cases and work around your problem.
> > You're right, I did not take the captures into account. OTOH > $c->req->path does not necessarily correspond to the path argument of > $c->uri_for() (that's exactly the reason why we have $c->uri_for(), > isn't it?:-). What do you think of this solution: > > $c->uri_for( > $c->action, $c->req->captures, > @{$c->req->arguments}, > $c->req->params > ); > > According the documentation of Catalyst::uri_for(), if $path is an action > object and the first argument after it is an array ref, it is considered > as the list of captures, and is passed to > $c->dispatcher->uri_for_action() along with the action object. So, if the > dispatcher can reconstruct the path from the action object and the > captures, it works. Now the question is how much can we depend on it (ie. > that uri_for_action() works well).
My note about "complex regexp actions" was specifically because uri_for_action can't work universally. How about reusing $c->req->uri to get the query string? I honestly don't think uri_for_action is safe enough for this. Hmm. You still want to go via uri_for of course. What about my $uri = $c->uri_for('/'.$c->req->path); $uri->query($c->req->uri->query); ? That seems to fix the query param problem you have and still not rely on uri_for_action. If $c->req->path isn't the right thing then that's a separate problem and probably belongs on catalyst-dev@lists.scsys.co.uk Show quoted text
> For Catalyst::DispatchType::Regex I just filed a bug report (rt.cpan.org > #39369), as its uri_for_action() is totally broken. But even if my patch > is accepted, the implementation is still admittedly weak (eg. it cannot > cope with nested parentheses according to the documentation), and it's no > surprise, as the task is inherently very tough (to reconstruct the > original string that was matched from the regex and captures).
Yes, I know. I wrote the original code for that (and all of Chained) and basically implemented uri_for_action for regexp to "mostly work" - I didn't try and cover many edge cases because once you go into edge cases it gets harder and harder, and was frankly pleasantly surprised I managed to make it work at all :) - but please note that the correct place to discuss changes to things is the catalyst-dev@ list, most of the relevant people aren't on rt so you'll get long ping times like we've had here. Once we get capture matching for Chained so you can do something like CaptureArgs(qr/\d+/) or similar, then Regexp basically becomes obsolete, which was always my intention, and then it becomes a much simpler thing. Show quoted text
> > A better solution for -you- IMO would be if you captured the language > > via a > > > > sub lang :Chained('/') :CaptureArgs(1) { > > > > action - then this would all work already; mangling $c->req->path is > > dangerous and highly inadvisable.
> > Thanks for pointing it out. In fact I perused the manual of > Catalyst::DispatchType::Chained twice before we settled with the > prepare_path() + uri_for() hack, as I felt that it's something very > close, but somehow it did not lend itself as the solution we looked for. > It did not get through for me that there need not be one predetermined > endpoint for each chain. I'll convert our app to use Chained soon.
Well, there is a predetermined end point, but you can chain lots of things off one start point :) Anyway, that conversation should continue on the mailing list if at all. -- Matt S Trout Need help with your Catalyst or DBIx::Class project? Technical Director http://www.shadowcat.co.uk/catalyst/ Shadowcat Systems Ltd. Want a managed development or deployment platform? http://chainsawblues.vox.com/ http://www.shadowcat.co.uk/servers/