[Catalyst-commits] r13263 - in Catalyst-Runtime/5.80/trunk: . lib lib/Catalyst/Engine t/aggregate t/lib

t0m at dev.catalyst.perl.org t0m at dev.catalyst.perl.org
Sat May 15 09:42:58 GMT 2010


Author: t0m
Date: 2010-05-15 10:42:58 +0100 (Sat, 15 May 2010)
New Revision: 13263

Modified:
   Catalyst-Runtime/5.80/trunk/
   Catalyst-Runtime/5.80/trunk/lib/Catalyst.pm
   Catalyst-Runtime/5.80/trunk/lib/Catalyst/Engine/CGI.pm
   Catalyst-Runtime/5.80/trunk/t/aggregate/live_component_controller_args.t
   Catalyst-Runtime/5.80/trunk/t/aggregate/unit_core_engine_cgi-prepare_path.t
   Catalyst-Runtime/5.80/trunk/t/lib/TestApp.pm
Log:
 r13208 at spaceinvaders (orig r13172):  t0m | 2010-04-19 09:54:56 +0200
 Branch to try and fix the request uri stuff.
 
 r13209 at spaceinvaders (orig r13173):  t0m | 2010-04-19 09:58:37 +0200
 Just add comments to tests, no functional changes
 r13210 at spaceinvaders (orig r13174):  t0m | 2010-04-19 09:59:14 +0200
 Get it mostly working, except uri_for is still buggered
 r15488 at spaceinvaders (orig r13192):  t0m | 2010-05-03 00:26:22 +0200
 Revert to old behaviour, allow config for new behaviour. Config option name is rubbish, needs fixing
 r15532 at spaceinvaders (orig r13236):  t0m | 2010-05-09 01:09:01 +0200
 I hate this name less. Others may feel differently
 r15556 at spaceinvaders (orig r13260):  t0m | 2010-05-15 10:52:16 +0200
 Simplify madness some more, back to how it looked in the original fix_path_info_decoding branch so that we aren't using dodgy heuristics to determine the path. Alter the prepare_path tests so that they're testing the appropriate config option so that we now have tests for both code paths
 r15557 at spaceinvaders (orig r13261):  t0m | 2010-05-15 11:20:16 +0200
 Add a pile of docs for the new use_request_uri_for_path setting
 r15558 at spaceinvaders (orig r13262):  t0m | 2010-05-15 11:38:06 +0200
 Add recommendation



Property changes on: Catalyst-Runtime/5.80/trunk
___________________________________________________________________
Modified: svk:merge
   - 1c72fc7c-9ce4-42af-bf25-3bfe470ff1e8:/local/Catalyst/trunk/Catalyst-Runtime:9763
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.70/branches/compres:7999
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.70/branches/context_go:8001
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.70/trunk:8533
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/Catalyst-Test-Updates:8363
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/add_captures_to_visit:9546
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/aggregate_more:11803
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/better_scripts:12074
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/disable_regex_fallback:11456
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/fix_path_info_decoding:12089
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/index_default_fuckage:10646
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/moose:7911
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/namespace_handling_refactor:10655
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/param_filtering:13012
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/uri_encode_captures_andor_args_take2:11811
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/uri_for_utf8:12834
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-ChildOf:4443
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-Runtime-jrockway:5857
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-component-setup:4320
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-docs:4325
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/current/Catalyst-Runtime:5142
4ad37cd2-5fec-0310-835f-b3785c72a374:/trunk/Catalyst:4483
4ad37cd2-5fec-0310-835f-b3785c72a374:/trunk/Catalyst-Runtime:6165
6d45476b-5895-46b8-b13a-8b969fa34c98:/local/Catalyst-Runtime-better_scripts:11331
8a9521aa-ff93-41d6-9f87-b05cafcdab40:/local/cat/Catalyst-Runtime/5.80/trunk:8157
d7608cd0-831c-0410-93c0-e5b306c3c028:/local/Catalyst/Catalyst-Runtime:8339
d7608cd0-831c-0410-93c0-e5b306c3c028:/local/Catalyst/Catalyst-Runtime-jrockway:8342
e56d974f-7718-0410-8b1c-b347a71765b2:/local/Catalyst-Runtime:6511
e56d974f-7718-0410-8b1c-b347a71765b2:/local/Catalyst-Runtime-current:10442
   + 1c72fc7c-9ce4-42af-bf25-3bfe470ff1e8:/local/Catalyst/trunk/Catalyst-Runtime:9763
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.70/branches/compres:7999
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.70/branches/context_go:8001
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.70/trunk:8533
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/Catalyst-Test-Updates:8363
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/add_captures_to_visit:9546
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/aggregate_more:11803
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/better_scripts:12074
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/disable_regex_fallback:11456
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/fix_path_info_decoding:12089
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/fix_request_uri:13262
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/index_default_fuckage:10646
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/moose:7911
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/namespace_handling_refactor:10655
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/param_filtering:13012
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/uri_encode_captures_andor_args_take2:11811
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.80/branches/uri_for_utf8:12834
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-ChildOf:4443
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-Runtime-jrockway:5857
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-component-setup:4320
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-docs:4325
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/current/Catalyst-Runtime:5142
4ad37cd2-5fec-0310-835f-b3785c72a374:/trunk/Catalyst:4483
4ad37cd2-5fec-0310-835f-b3785c72a374:/trunk/Catalyst-Runtime:6165
6d45476b-5895-46b8-b13a-8b969fa34c98:/local/Catalyst-Runtime-better_scripts:11331
8a9521aa-ff93-41d6-9f87-b05cafcdab40:/local/cat/Catalyst-Runtime/5.80/trunk:8157
d7608cd0-831c-0410-93c0-e5b306c3c028:/local/Catalyst/Catalyst-Runtime:8339
d7608cd0-831c-0410-93c0-e5b306c3c028:/local/Catalyst/Catalyst-Runtime-jrockway:8342
e56d974f-7718-0410-8b1c-b347a71765b2:/local/Catalyst-Runtime:6511
e56d974f-7718-0410-8b1c-b347a71765b2:/local/Catalyst-Runtime-current:10442

Modified: Catalyst-Runtime/5.80/trunk/lib/Catalyst/Engine/CGI.pm
===================================================================
--- Catalyst-Runtime/5.80/trunk/lib/Catalyst/Engine/CGI.pm	2010-05-15 09:38:06 UTC (rev 13262)
+++ Catalyst-Runtime/5.80/trunk/lib/Catalyst/Engine/CGI.pm	2010-05-15 09:42:58 UTC (rev 13263)
@@ -28,6 +28,43 @@
 
 This is the Catalyst engine specialized for the CGI environment.
 
+=head1 PATH DECODING
+
+Most web server environments pass the requested path to the application using environment variables,
+from which Catalyst has to reconstruct the request base (i.e. the top level path to / in the application,
+exposed as C<< $c->request->base >>) and the request path below that base.
+
+There are two methods of doing this, both of which have advantages and disadvantages. Which method is used
+is determined by the C<< $c->config(use_request_uri_for_path) >> setting (which can either be true or false).
+
+=head2 use_request_uri_for_path => 0
+
+This is the default (and the) traditional method that Catalyst has used for determining the path information.
+The path is synthesised from a combination of the C<PATH_INFO> and C<SCRIPT_NAME> environment variables.
+The allows the application to behave correctly when C<mod_rewrite> is being used to redirect requests
+into the application, as these variables are adjusted by mod_rewrite to take account for the redirect.
+
+However this method has the major disadvantage that it is impossible to correctly decode some elements
+of the path, as RFC 3875 says: "C<< Unlike a URI path, the PATH_INFO is not URL-encoded, and cannot
+contain path-segment parameters. >>" This means PATH_INFO is B<always> decoded, and therefore Catalyst
+can't distinguish / vs %2F in paths (in addition to other encoded values).
+
+=head2 use_request_uri_for_path => 1
+
+This method uses the C<REQUEST_URI> and C<SCRIPT_NAME> environment variables. As C<REQUEST_URI> is never
+decoded, this means that applications using this mode can correctly handle URIs including the %2F character
+(i.e. with C<AllowEncodedSlashes> set to C<On> in Apache).
+
+Given that this method of path resolution is provably more correct, it is recommended that you use
+this unless you have a specific need to deploy your application in a non-standard environment, and you are
+aware of the implications of not being able to handle encoded URI paths correctly.
+
+However it also means that in a number of cases when the app isn't installed directly at a path, but instead
+is having paths rewritten into it (e.g. as a .cgi/fcgi in a public_html directory, with mod_rewrite in a
+.htaccess file, or when SSI is used to rewrite pages into the app, or when sub-paths of the app are exposed
+at other URIs than that which the app is 'normally' based at with C<mod_rewrite>), the resolution of
+C<< $c->request->base >> will be incorrect.
+
 =head1 OVERLOADED METHODS
 
 This class overloads some methods from C<Catalyst::Engine>.
@@ -148,30 +185,19 @@
         }
     }
 
-    # RFC 3875: "Unlike a URI path, the PATH_INFO is not URL-encoded,
-    # and cannot contain path-segment parameters." This means PATH_INFO
-    # is always decoded, and the script can't distinguish / vs %2F.
-    # See https://issues.apache.org/bugzilla/show_bug.cgi?id=35256
-    # Here we try to resurrect the original encoded URI from REQUEST_URI.
     my $path_info   = $ENV{PATH_INFO};
-    if (my $req_uri = $ENV{REQUEST_URI}) {
-        $req_uri =~ s/^\Q$base_path\E//;
-        $req_uri =~ s/\?.*$//;
-        if ($req_uri) {
-            # Note that if REQUEST_URI doesn't start with a /, then the user
-            # is probably using mod_rewrite or something to rewrite requests
-            # into a sub-path of their application..
-            # This means that REQUEST_URI needs information from PATH_INFO
-            # prepending to it to be useful, otherwise the sub path which is
-            # being redirected to becomes the app base address which is
-            # incorrect.
-            if (substr($req_uri, 0, 1) ne '/') {
-                my ($match) = $req_uri =~ m|^([^/]+)|;
-                my ($path_info_part) = $path_info =~ m|^(.*?\Q$match\E)|;
-                substr($req_uri, 0, length($match), $path_info_part)
-                    if $path_info_part;
+    if ($c->config->{use_request_uri_for_path}) {
+        # RFC 3875: "Unlike a URI path, the PATH_INFO is not URL-encoded,
+        # and cannot contain path-segment parameters." This means PATH_INFO
+        # is always decoded, and the script can't distinguish / vs %2F.
+        # See https://issues.apache.org/bugzilla/show_bug.cgi?id=35256
+        # Here we try to resurrect the original encoded URI from REQUEST_URI.
+        if (my $req_uri = $ENV{REQUEST_URI}) {
+            if (defined $script_name) {
+                $req_uri =~ s/^\Q$script_name\E//;
             }
-            $path_info = $req_uri;
+            $req_uri =~ s/\?.*$//;
+            $path_info = $req_uri if $req_uri;
         }
     }
 

Modified: Catalyst-Runtime/5.80/trunk/lib/Catalyst.pm
===================================================================
--- Catalyst-Runtime/5.80/trunk/lib/Catalyst.pm	2010-05-15 09:38:06 UTC (rev 13262)
+++ Catalyst-Runtime/5.80/trunk/lib/Catalyst.pm	2010-05-15 09:42:58 UTC (rev 13263)
@@ -2946,6 +2946,12 @@
 
 =item *
 
+C<use_request_uri_for_path> - Controlls if the C<REQUEST_URI> or C<PATH_INFO> environment
+variable should be used for determining the request path. See L<Catalyst::Engine::CGI/PATH DECODING>
+for more information.
+
+=item *
+
 C<using_frontend_proxy> - See L</PROXY SUPPORT>.
 
 =back

Modified: Catalyst-Runtime/5.80/trunk/t/aggregate/live_component_controller_args.t
===================================================================
--- Catalyst-Runtime/5.80/trunk/t/aggregate/live_component_controller_args.t	2010-05-15 09:38:06 UTC (rev 13262)
+++ Catalyst-Runtime/5.80/trunk/t/aggregate/live_component_controller_args.t	2010-05-15 09:42:58 UTC (rev 13263)
@@ -73,15 +73,15 @@
 
         my $response;
 
-        ok( $response = request("http://localhost/args/args/$path"), "Requested args for path $path");
+        ok( $response = request("http://localhost/args/args/$path"), "Requested /args/args/$path");
 
         is( $response->content, $test, "$test as args" );
 
         undef $response;
 
-        ok( $response = request("http://localhost/args/params/$path"), "Requested params for path $path");
+        ok( $response = request("http://localhost/args/params/$path"), "Requested /args/params/$path");
 
-        is( $response->content, $test, "$test as params" );
+        is( $response->content, $test, "response content $test as params" );
 
         undef $response;
 

Modified: Catalyst-Runtime/5.80/trunk/t/aggregate/unit_core_engine_cgi-prepare_path.t
===================================================================
--- Catalyst-Runtime/5.80/trunk/t/aggregate/unit_core_engine_cgi-prepare_path.t	2010-05-15 09:38:06 UTC (rev 13262)
+++ Catalyst-Runtime/5.80/trunk/t/aggregate/unit_core_engine_cgi-prepare_path.t	2010-05-15 09:42:58 UTC (rev 13263)
@@ -8,18 +8,18 @@
 
 # mod_rewrite to app root for non / based app
 {
-    my $r = get_req (
+    my $r = get_req (0,
         REDIRECT_URL => '/comics/',
         SCRIPT_NAME => '/comics/dispatch.cgi',
         REQUEST_URI => '/comics/',
     );
-    is ''.$r->uri, 'http://www.foo.com/comics/';
-    is ''.$r->base, 'http://www.foo.com/comics/';
+    is ''.$r->uri, 'http://www.foo.com/comics/', 'uri is correct';
+    is ''.$r->base, 'http://www.foo.com/comics/', 'base is correct';
 }
 
 # mod_rewrite to sub path under app root for non / based app
 {
-    my $r = get_req (
+    my $r = get_req (0,
         PATH_INFO  => '/foo/bar.gif',
         REDIRECT_URL => '/comics/foo/bar.gif',
         SCRIPT_NAME => '/comics/dispatch.cgi',
@@ -31,7 +31,7 @@
 
 # Standard CGI hit for non / based app
 {
-    my $r = get_req (
+    my $r = get_req (0,
         PATH_INFO => '/static/css/blueprint/screen.css',
         SCRIPT_NAME => '/~bobtfish/Gitalist/script/gitalist.cgi',
         REQUEST_URI => '/~bobtfish/Gitalist/script/gitalist.cgi/static/css/blueprint/screen.css',
@@ -41,19 +41,19 @@
 }
 # / %2F %252F escaping case.
 {
-    my $r = get_req (
+    my $r = get_req (1,
         PATH_INFO => '/%2F/%2F',
         SCRIPT_NAME => '/~bobtfish/Gitalist/script/gitalist.cgi',
         REQUEST_URI => '/~bobtfish/Gitalist/script/gitalist.cgi/%252F/%252F',
     );
-    is ''.$r->uri, 'http://www.foo.com/~bobtfish/Gitalist/script/gitalist.cgi/%252F/%252F';
-    is ''.$r->base, 'http://www.foo.com/~bobtfish/Gitalist/script/gitalist.cgi/';
+    is ''.$r->uri, 'http://www.foo.com/~bobtfish/Gitalist/script/gitalist.cgi/%252F/%252F', 'uri correct';
+    is ''.$r->base, 'http://www.foo.com/~bobtfish/Gitalist/script/gitalist.cgi/', 'base correct';
 }
 
 # Using rewrite rules to ask for a sub-path in your app.
 # E.g. RewriteRule ^(.*)$ /path/to/fastcgi/domainprofi.fcgi/iframeredirect$1 [L,NS]
 {
-    my $r = get_req (
+    my $r = get_req (0,
         PATH_INFO => '/iframeredirect/info',
         SCRIPT_NAME => '',
         REQUEST_URI => '/info',
@@ -64,7 +64,7 @@
 
 # nginx example from espent with path /"foo"
 {
-    my $r = get_req (
+    my $r = get_req (0,
         PATH_INFO => '"foo"',
         SCRIPT_NAME => '/',
         REQUEST_URI => '/%22foo%22',
@@ -76,33 +76,33 @@
 
 # nginx example from espent with path /"foo" and the app based at /oslobilder
 {
-    my $r = get_req (
+    my $r = get_req (1,
         PATH_INFO => 'oslobilder/"foo"',
         SCRIPT_NAME => '/oslobilder/',
         REQUEST_URI => '/oslobilder/%22foo%22',
     );
-    is ''.$r->path, '%22foo%22';
-    is ''.$r->uri, 'http://www.foo.com/oslobilder/%22foo%22';
-    is ''.$r->base, 'http://www.foo.com/oslobilder/';
+    is ''.$r->path, '%22foo%22', 'path correct';
+    is ''.$r->uri, 'http://www.foo.com/oslobilder/%22foo%22', 'uri correct';
+    is ''.$r->base, 'http://www.foo.com/oslobilder/', 'base correct';
 }
 
 {
     local $TODO = 'Another mod_rewrite case';
-    my $r = get_req (
+    my $r = get_req (0,
         PATH_INFO => '/auth/login',
         SCRIPT_NAME => '/tx',
         REQUEST_URI => '/login',
     );
-    is ''.$r->path, 'auth/login';
-    is ''.$r->uri, 'http://www.foo.com/tx/auth/login';
-    is ''.$r->base, 'http://www.foo.com/tx/';
+    is ''.$r->path, 'auth/login', 'path correct';
+    is ''.$r->uri, 'http://www.foo.com/tx/auth/login', 'uri correct';
+    is ''.$r->base, 'http://www.foo.com/tx/', 'base correct';
 }
 
 # test req->base and c->uri_for work correctly after an internally redirected request
 # (i.e. REDIRECT_URL set) when the PATH_INFO contains a regex
 {
     my $path = '/engine/request/uri/Rx(here)';
-    my $r = get_req (
+    my $r = get_req (0,
         SCRIPT_NAME => '/',
         PATH_INFO => $path,
         REQUEST_URI => $path,
@@ -121,6 +121,8 @@
 #       - Test scheme (secure request on port 80)
 
 sub get_req {
+    my $use_request_uri_for_path = shift;
+
     my %template = (
         HTTP_HOST => 'www.foo.com',
         PATH_INFO => '/',
@@ -129,6 +131,9 @@
     local %ENV = (%template, @_);
 
     my $i = TestApp->new;
+    $i->setup_finished(0);
+    $i->config(use_request_uri_for_path => $use_request_uri_for_path);
+    $i->setup_finished(1);
     $i->engine(Catalyst::Engine::CGI->new);
     $i->engine->prepare_path($i);
     return $i->req;

Modified: Catalyst-Runtime/5.80/trunk/t/lib/TestApp.pm
===================================================================
--- Catalyst-Runtime/5.80/trunk/t/lib/TestApp.pm	2010-05-15 09:38:06 UTC (rev 13262)
+++ Catalyst-Runtime/5.80/trunk/t/lib/TestApp.pm	2010-05-15 09:42:58 UTC (rev 13263)
@@ -18,7 +18,7 @@
 
 our $VERSION = '0.01';
 
-TestApp->config( name => 'TestApp', root => '/some/dir' );
+TestApp->config( name => 'TestApp', root => '/some/dir', use_request_uri_for_path => 1 );
 
 if ($::setup_leakchecker && eval { Class::MOP::load_class('CatalystX::LeakChecker'); 1 }) {
     with 'CatalystX::LeakChecker';




More information about the Catalyst-commits mailing list