Skip Menu |

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

Report information
The Basics
Id: 34525
Status: resolved
Priority: 0/
Queue: Catalyst-Runtime

People
Owner: bobtfish [...] bobtfish.net
Requestors: mods [...] hank.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 5.70_03
Fixed in: (no value)



Subject: Catalyst does not decode %-encoded paths when matching actions
Catalyst does not decode %-encoded paths when matching actions. register_path() does try and convert action names into URIs before matching but that's a broken approach because it will only percent-encode what must be encoded, where a url can have any byte percent-encoded. The correct approach, of course, is to decode the percent escapes from the path, then utf8 decode that. Then match the actions. see: http://lists.scsys.co.uk/pipermail/catalyst/2008-March/017917.html
On Sat Mar 29 10:09:50 2008, HANK wrote: Show quoted text
> Catalyst does not decode %-encoded paths when matching actions.
Can you provide a failing test case?
From: mods [...] hank.org
On Tue May 27 08:16:29 2008, BRICAS wrote: Show quoted text
> On Sat Mar 29 10:09:50 2008, HANK wrote:
> > Catalyst does not decode %-encoded paths when matching actions.
> > Can you provide a failing test case?
See attached test. Note that cannot use Catalyst::Test to test this problem because it uses HTTP::Request::AsCGI and that module *fixes* the issue, where Catalyst (or really the engines) fail to. So, the attached test uses AsCGI directly and then "un-fixes" the PATH_INFO environment to expose the problem. There's a patch included in the test, but it's not a complete fix since each engine would need to be fixed. There's too much common code in the engines.
#!perl use strict; use warnings; use FindBin; use lib "$FindBin::Bin/lib"; use Test::More tests => 6; use TestApp; use HTTP::Request::AsCGI; =cut This test exposes a problem in the handling of PATH_INFO in C::Engine::CGI (and other engines) where Catalyst does not un-escape the request correctly. If a request is URL-encoded then Catalyst fails to decode the request and thus will try and match actions using the URL-encoded value. Can NOT use Catalyst::Test as it uses HTTP::Request::AsCGI which does correctly unescape the path (by calling $uri = $uri->canonical). $ prove -vl t/live_engine_request_escaped_path.t t/live_engine_request_escaped_path...... 1..6 got path [args/params/one/two] ok 1 ok 2 - Response Successful 2xx ok 3 got path [args/param%73/one/two] ok 4 not ok 5 - Response Successful 2xx # Failed test 'Response Successful 2xx' # at t/live_engine_request_escaped_path.t line 53. not ok 6 # Failed test at t/live_engine_request_escaped_path.t line 54. # got: 'FATAL ERROR: Unknown resource "args/param%73/one/two"' # expected: 'onetwo' # Looks like you failed 2 tests of 6. # As can be seen, Catalyst tried to match "args/param%73/one/two" This will fix the problem for the CGI engine, but is probably the wrong place. And also does not fix $uri->base, either. Plus, the same issue is in Engine::Apache* and other engines. Index: lib/Catalyst/Engine/CGI.pm =================================================================== --- lib/Catalyst/Engine/CGI.pm (revision 7821) +++ lib/Catalyst/Engine/CGI.pm (working copy) @@ -157,6 +157,8 @@ my $query = $ENV{QUERY_STRING} ? '?' . $ENV{QUERY_STRING} : ''; my $uri = $scheme . '://' . $host . '/' . $path . $query; + $uri = URI->new( $uri )->canonical; + $c->request->uri( bless \$uri, $uri_class ); # set the base URI =cut # test that un-escaped can be feteched. { my $request = Catalyst::Utils::request( 'http://localhost/args/params/one/two' ); my $cgi = HTTP::Request::AsCGI->new( $request, %ENV )->setup; TestApp->handle_request; ok( my $response = $cgi->restore->response ); ok( $response->is_success, 'Response Successful 2xx' ); is( $response->content, 'onetwo' ); } # test that request with URL-escaped code works. { my $request = Catalyst::Utils::request( 'http://localhost/args/para%73/one/two' ); my $cgi = HTTP::Request::AsCGI->new( $request, %ENV )->setup; # Reset PATH_INFO because AsCGI calls $uri = $uri->canonical which # will unencode the path and hide the problem from the test. $ENV{PATH_INFO} = '/args/param%73/one/two'; TestApp->handle_request; ok( my $response = $cgi->restore->response ); ok( $response->is_success, 'Response Successful 2xx' ); is( $response->content, 'onetwo' ); }
Test committed: http://dev.catalyst.perl.org/svnweb/Catalyst/revision/?rev=10700 Sorry about the glacial progress on this.
This issue is resolved in the latest dev release, Catalyst 5.80014_02. Thanks for reporting this and providing a test case (which now passes!), sorry it took so long to sort out.