[Catalyst-commits] r6233 - in trunk/Catalyst-Engine-Apache: . lib/Catalyst/Engine lib/Catalyst/Engine/Apache lib/Catalyst/Engine/Apache2 t

andyg at dev.catalyst.perl.org andyg at dev.catalyst.perl.org
Thu Mar 29 04:00:44 GMT 2007


Author: andyg
Date: 2007-03-29 04:00:42 +0100 (Thu, 29 Mar 2007)
New Revision: 6233

Modified:
   trunk/Catalyst-Engine-Apache/Changes
   trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache.pm
   trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache/MP13.pm
   trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache2/MP19.pm
   trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache2/MP20.pm
   trunk/Catalyst-Engine-Apache/t/live_component_controller_args.t
   trunk/Catalyst-Engine-Apache/t/live_engine_request_parameters.t
Log:
Apache engine: refactored prepare_path to avoid URI.pm.  Use Apache C-based URI unescaping during prepare_query_parameters

Modified: trunk/Catalyst-Engine-Apache/Changes
===================================================================
--- trunk/Catalyst-Engine-Apache/Changes	2007-03-29 02:58:01 UTC (rev 6232)
+++ trunk/Catalyst-Engine-Apache/Changes	2007-03-29 03:00:42 UTC (rev 6233)
@@ -1,7 +1,11 @@
 This file documents the revision history for Catalyst::Engine::Apache.
 
+1.08
+        - Improved prepare_query_parameters performance by using C-based
+          Apache modules instead of URI and URI::Escape.
+        - Improved prepare_path performance by removing the use of URI.pm.
         - Extract host and port from X-Forwarded-Host.
-        - Use Apache2::ModSSL if available.
+        - Use Apache2::ModSSL for determining SSL mode if available.
 
 1.07    2006-02-17 17:00:00
         - Fixed bug: Can't locate object method "FIRSTKEY" via package

Modified: trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache/MP13.pm
===================================================================
--- trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache/MP13.pm	2007-03-29 02:58:01 UTC (rev 6232)
+++ trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache/MP13.pm	2007-03-29 03:00:42 UTC (rev 6233)
@@ -7,6 +7,7 @@
 use Apache            ();
 use Apache::Constants qw(OK);
 use Apache::File      ();
+use Apache::Util      ();
 
 sub finalize_headers {
     my ( $self, $c ) = @_;
@@ -20,6 +21,13 @@
 
 sub ok_constant { Apache::Constants::OK }
 
+sub unescape_uri {
+    my $self = shift;
+
+    # Unlike in mod_perl 2, this method also unescapes '+' to space
+    return Apache::Util::unescape_uri_info(@_);
+}
+
 1;
 __END__
 

Modified: trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache.pm
===================================================================
--- trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache.pm	2007-03-29 02:58:01 UTC (rev 6232)
+++ trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache.pm	2007-03-29 03:00:42 UTC (rev 6233)
@@ -7,7 +7,7 @@
 use File::Spec;
 use URI;
 
-our $VERSION = '1.07';
+our $VERSION = '1.08';
 
 __PACKAGE__->mk_accessors(qw/apache return/);
 
@@ -40,7 +40,6 @@
     $c->request->protocol( $self->apache->protocol );
     $c->request->user( $self->apache->user );
 
-
     # when config options are set, check them here first
     if ($INC{'Apache2/ModSSL.pm'}) {
         $c->request->secure(1) if $self->apache->connection->is_https;
@@ -53,8 +52,8 @@
 
 sub prepare_query_parameters {
     my ( $self, $c ) = @_;
-
-    if ( my $query_string = $self->apache->args ) { # stringify
+    
+    if ( my $query_string = $self->apache->args ) {
         $self->SUPER::prepare_query_parameters( $c, $query_string );
     }
 }
@@ -72,6 +71,7 @@
 sub prepare_path {
     my ( $self, $c ) = @_;
 
+    my $scheme = $c->request->secure ? 'https' : 'http';
     my $host   = $self->apache->hostname || 'localhost';
     my $port   = $self->apache->get_server_port;
 
@@ -96,40 +96,54 @@
         }
     }
 
+    my $base_path = '';
 
-    my $base_path = q{};
-
     # Are we running in a non-root Location block?
     my $location = $self->apache->location;
     if ( $location && $location ne '/' ) {
         $base_path = $location;
     }
+    
+    # base must end in a slash
+    $base_path .= '/' unless $base_path =~ m{/$};
 
     # Are we an Apache::Registry script? Why anyone would ever want to run
     # this way is beyond me, but we'll support it!
+    # XXX: This needs a test
     if ( defined $ENV{SCRIPT_NAME} && $self->apache->filename && -f $self->apache->filename && -x _ ) {
         $base_path .= $ENV{SCRIPT_NAME};
     }
+    
+    # Using URI directly is way too slow, so we construct the URLs manually
+    my $uri_class = "URI::$scheme";
+    
+    if ( $port != 80 && $host !~ /:/ ) {
+        $host .= ":$port";
+    }
+    
+    # Escape the path
+    my $path = $self->apache->uri;
+    $path   =~ s{^/+}{};
+    $path   =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
+    $path   =~ s/\?/%3F/g; # STUPID STUPID SPECIAL CASE
+    
+    # If the path is contained within the base, we need to make the path
+    # match base.  This handles the case where the app is running at /deep/path
+    # but a request to /deep/path fails where /deep/path/ does not.
+    if ( $base_path ne '/' && $base_path ne $path && $base_path =~ m{/$path} ) {
+        $path = $base_path;
+        $path =~ s{^/+}{};
+    }
+    
+    my $qs    = $self->apache->args;
+    my $query = $qs ? '?' . $qs : '';
+    my $uri   = $scheme . '://' . $host . '/' . $path . $query;
 
-    my $uri = URI->new;
-    $uri->scheme( $c->request->secure ? 'https' : 'http' );
-    $uri->host($host);
-    $uri->port($port);
-    $uri->path( $self->apache->uri );
-    my $query_string = $self->apache->args;
-    $uri->query( $query_string );
+    $c->request->uri( bless \$uri, $uri_class );
+    
+    my $base_uri = $scheme . '://' . $host . $base_path;
 
-    # sanitize the URI
-    $uri = $uri->canonical;
-    $c->request->uri( $uri );
-
-    # set the base URI
-    # base must end in a slash
-    $base_path .= '/' unless $base_path =~ m{/$};
-    my $base = $uri->clone;
-    $base->path_query( $base_path );
-    $base = $base->canonical;
-    $c->request->base( $base );
+    $c->request->base( bless \$base_uri, $uri_class );
 }
 
 sub read_chunk {

Modified: trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache2/MP19.pm
===================================================================
--- trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache2/MP19.pm	2007-03-29 02:58:01 UTC (rev 6232)
+++ trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache2/MP19.pm	2007-03-29 03:00:42 UTC (rev 6233)
@@ -11,9 +11,19 @@
 use Apache::RequestRec  ();
 use Apache::RequestUtil ();
 use Apache::Response    ();
+use Apache::URI         ();
 
 sub ok_constant { Apache::OK }
 
+sub unescape_uri {
+    my $self = shift;
+
+    my $e = Apache::URI::unescape_url(@_);
+    $e =~ s/\+/ /g;
+    
+    return $e;
+}
+
 1;
 __END__
 

Modified: trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache2/MP20.pm
===================================================================
--- trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache2/MP20.pm	2007-03-29 02:58:01 UTC (rev 6232)
+++ trunk/Catalyst-Engine-Apache/lib/Catalyst/Engine/Apache2/MP20.pm	2007-03-29 03:00:42 UTC (rev 6233)
@@ -10,11 +10,23 @@
 use Apache2::RequestRec  ();
 use Apache2::RequestUtil ();
 use Apache2::Response    ();
+use Apache2::URI         ();
 use APR::Table           ();
-eval "require Apache2::ModSSL";
 
+# We can use Apache2::ModSSL to better detect if we're running in SSL mode
+eval { require Apache2::ModSSL };
+
 sub ok_constant { Apache2::Const::OK }
 
+sub unescape_uri {
+    my $self = shift;
+
+    my $e = Apache2::URI::unescape_url(@_);
+    $e =~ s/\+/ /g;
+    
+    return $e;
+}
+
 1;
 __END__
 

Modified: trunk/Catalyst-Engine-Apache/t/live_component_controller_args.t
===================================================================
--- trunk/Catalyst-Engine-Apache/t/live_component_controller_args.t	2007-03-29 02:58:01 UTC (rev 6232)
+++ trunk/Catalyst-Engine-Apache/t/live_component_controller_args.t	2007-03-29 03:00:42 UTC (rev 6233)
@@ -65,8 +65,9 @@
     
     SKIP:
     {   
-        # Skip %2F and . tests on real webservers, they are often ignored by default
-        if ( $ENV{CATALYST_SERVER} && $path =~ /(?:%2F|\.)/ ) {
+        # Skip %2F, ., [, (, and ) tests on real webservers
+        # Both Apache and lighttpd don't seem to like these
+        if ( $ENV{CATALYST_SERVER} && $path =~ /(?:%2F|\.|%5B|\(|\))/ ) {
             skip "Skipping $path tests on remote server", 6;
         }
 

Modified: trunk/Catalyst-Engine-Apache/t/live_engine_request_parameters.t
===================================================================
--- trunk/Catalyst-Engine-Apache/t/live_engine_request_parameters.t	2007-03-29 02:58:01 UTC (rev 6232)
+++ trunk/Catalyst-Engine-Apache/t/live_engine_request_parameters.t	2007-03-29 03:00:42 UTC (rev 6233)
@@ -6,7 +6,7 @@
 use FindBin;
 use lib "$FindBin::Bin/lib";
 
-use Test::More tests => 29;
+use Test::More tests => 30;
 use Catalyst::Test 'TestApp';
 
 use Catalyst::Request;
@@ -103,14 +103,15 @@
     };
 
     my $request = POST(
-        'http://localhost/dump/request/a/b?query_string',
+        'http://localhost/dump/request/a/b?query+string',
         'Content'      => $parameters,
         'Content-Type' => 'application/x-www-form-urlencoded'
     );
     
     ok( my $response = request($request), 'Request' );
     ok( eval '$creq = ' . $response->content, 'Unserialize Catalyst::Request' );
-    is( $creq->{uri}->query, 'query_string', 'Catalyst::Request POST query_string' );
+    is( $creq->{uri}->query, 'query+string', 'Catalyst::Request POST query_string' );
+    is( $creq->keywords, 'query string', 'Catalyst::Request keywords' );
     is_deeply( $creq->{parameters}, $parameters, 'Catalyst::Request parameters' );
     
     ok( $response = request('http://localhost/dump/request/a/b?x=1&y=1&z=1'), 'Request' );




More information about the Catalyst-commits mailing list