[Catalyst-commits] r6232 - in trunk/Catalyst-Runtime: . lib
lib/Catalyst lib/Catalyst/Engine t
andyg at dev.catalyst.perl.org
andyg at dev.catalyst.perl.org
Thu Mar 29 03:58:17 GMT 2007
Author: andyg
Date: 2007-03-29 03:58:01 +0100 (Thu, 29 Mar 2007)
New Revision: 6232
Modified:
trunk/Catalyst-Runtime/Changes
trunk/Catalyst-Runtime/lib/Catalyst.pm
trunk/Catalyst-Runtime/lib/Catalyst/Engine.pm
trunk/Catalyst-Runtime/lib/Catalyst/Engine/CGI.pm
trunk/Catalyst-Runtime/lib/Catalyst/Request.pm
trunk/Catalyst-Runtime/t/live_engine_request_parameters.t
Log:
Refactored prepare_path and prepare_query_parameters to avoid the use of URI.pm and improve performance. Added ->req->keywords method.
Modified: trunk/Catalyst-Runtime/Changes
===================================================================
--- trunk/Catalyst-Runtime/Changes 2007-03-29 02:53:04 UTC (rev 6231)
+++ trunk/Catalyst-Runtime/Changes 2007-03-29 02:58:01 UTC (rev 6232)
@@ -1,13 +1,18 @@
This file documents the revision history for Perl extension Catalyst.
5.7008 XXXX-XX-XX
- - Sending SIGHUP to the dev server will now cause it to restart.
- - Allow "0" for a path in uri_for.
- - Performance improvements to uri_for by inlining encoding.
+ - Many performance improvements by not using URI.pm:
+ * $c->uri_for (approx. 8x faster)
+ * $c->engine->prepare_path (approx. 27x faster)
+ * $c->engine->prepare_query_parameters (approx. 5x faster)
- Updated HTTP::Body dependency to 0.9 which fixes the following issues:
* Handle when IE sometimes sends an extra CRLF after the POST body.
* Empty fields in multipart/form-data POSTs are no longer ignored.
* Uploaded files with the name "0" are no longer ignored.
+ - Added $c->request->keywords for getting the keywords (a query string with
+ no parameters).
+ - Sending SIGHUP to the dev server will now cause it to restart.
+ - Allow "0" for a path in uri_for.
5.7007 2007-03-13 14:18:00
- Performance and stability improvements to the built-in HTTP server.
Modified: trunk/Catalyst-Runtime/lib/Catalyst/Engine/CGI.pm
===================================================================
--- trunk/Catalyst-Runtime/lib/Catalyst/Engine/CGI.pm 2007-03-29 02:53:04 UTC (rev 6231)
+++ trunk/Catalyst-Runtime/lib/Catalyst/Engine/CGI.pm 2007-03-29 02:58:01 UTC (rev 6232)
@@ -3,9 +3,7 @@
use strict;
use base 'Catalyst::Engine';
use NEXT;
-use URI;
-my $uri_proto=URI->new();
__PACKAGE__->mk_accessors('env');
=head1 NAME
@@ -137,26 +135,36 @@
$port = $c->request->secure ? 443 : 80;
}
- # set the base URI
- # base must end in a slash
- $base_path .= '/' unless ( $base_path =~ /\/$/ );
-
+ # set the request URI
my $path = $base_path . ( $ENV{PATH_INFO} || '' );
$path =~ s{^/+}{};
+
+ # Using URI directly is way too slow, so we construct the URLs manually
+ my $uri_class = "URI::$scheme";
+
+ # HTTP_HOST will include the port even if it's 80
+ $host =~ s/:80$//;
+
+ if ( $port != 80 && $host !~ /:/ ) {
+ $host .= ":$port";
+ }
+
+ # Escape the path
+ $path =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
+ $path =~ s/\?/%3F/g; # STUPID STUPID SPECIAL CASE
+
+ my $query = $ENV{QUERY_STRING} ? '?' . $ENV{QUERY_STRING} : '';
+ my $uri = $scheme . '://' . $host . '/' . $path . $query;
- my $uri = $uri_proto->clone;
- $uri->scheme($scheme);
- $uri->host($host);
- $uri->port($port);
- $uri->path($path);
- $uri->query( $ENV{QUERY_STRING} ) if $ENV{QUERY_STRING};
+ $c->request->uri( bless \$uri, $uri_class );
- # sanitize the URI
- $uri = $uri->canonical;
- $c->request->uri($uri);
- my $base = $uri->clone;
- $base->path_query($base_path);
- $c->request->base($base);
+ # set the base URI
+ # base must end in a slash
+ $base_path .= '/' unless $base_path =~ m{/$};
+
+ my $base_uri = $scheme . '://' . $host . $base_path;
+
+ $c->request->base( bless \$base_uri, $uri_class );
}
=head2 $self->prepare_query_parameters($c)
Modified: trunk/Catalyst-Runtime/lib/Catalyst/Engine.pm
===================================================================
--- trunk/Catalyst-Runtime/lib/Catalyst/Engine.pm 2007-03-29 02:53:04 UTC (rev 6231)
+++ trunk/Catalyst-Runtime/lib/Catalyst/Engine.pm 2007-03-29 02:58:01 UTC (rev 6232)
@@ -7,6 +7,7 @@
use HTML::Entities;
use HTTP::Body;
use HTTP::Headers;
+use URI::Escape ();
use URI::QueryParam;
use Scalar::Util ();
@@ -446,16 +447,42 @@
sub prepare_query_parameters {
my ( $self, $c, $query_string ) = @_;
+
+ # Check for keywords (no = signs)
+ if ( index( $query_string, '=' ) < 0 ) {
+ $c->request->keywords( $self->unescape_uri($query_string) );
+ return;
+ }
+ my %query;
+
# replace semi-colons
$query_string =~ s/;/&/g;
+
+ my @params = split /&/, $query_string;
- my $u = URI->new( '', 'http' );
- $u->query($query_string);
- for my $key ( $u->query_param ) {
- my @vals = $u->query_param($key);
- $c->request->query_parameters->{$key} = @vals > 1 ? [@vals] : $vals[0];
+ for my $item ( @params ) {
+
+ my ($param, $value)
+ = map { $self->unescape_uri($_) }
+ split( /=/, $item );
+
+ $param = $self->unescape_uri($item) unless defined $param;
+
+ if ( exists $query{$param} ) {
+ if ( ref $query{$param} ) {
+ push @{ $query{$param} }, $value;
+ }
+ else {
+ $query{$param} = [ $query{$param}, $value ];
+ }
+ }
+ else {
+ $query{$param} = $value;
+ }
}
+
+ $c->request->query_parameters( \%query );
}
=head2 $self->prepare_read($c)
@@ -607,7 +634,22 @@
print STDOUT $buffer;
}
+=head2 $self->unescape_uri($uri)
+Unescapes a given URI using the most efficient method available. Engines such
+as Apache may implement this using Apache's C-based modules, for example.
+
+=cut
+
+sub unescape_uri {
+ my $self = shift;
+
+ my $e = URI::Escape::uri_unescape(@_);
+ $e =~ s/\+/ /g;
+
+ return $e;
+}
+
=head2 $self->finalize_output
<obsolete>, see finalize_body
Modified: trunk/Catalyst-Runtime/lib/Catalyst/Request.pm
===================================================================
--- trunk/Catalyst-Runtime/lib/Catalyst/Request.pm 2007-03-29 02:53:04 UTC (rev 6231)
+++ trunk/Catalyst-Runtime/lib/Catalyst/Request.pm 2007-03-29 02:58:01 UTC (rev 6232)
@@ -9,7 +9,7 @@
use URI::QueryParam;
__PACKAGE__->mk_accessors(
- qw/action address arguments cookies headers match method
+ qw/action address arguments cookies headers keywords match method
protocol query_parameters secure captures uri user/
);
@@ -51,6 +51,7 @@
$req->headers;
$req->hostname;
$req->input;
+ $req->keywords;
$req->match;
$req->method;
$req->param;
@@ -259,6 +260,15 @@
Alias for $req->body.
+=head2 $req->keywords
+
+Contains the keywords portion of a query string, when no '=' signs are
+present.
+
+ http://localhost/path?some+keywords
+
+ $c->request->keywords will contain 'some keywords'
+
=head2 $req->match
This contains the matching part of a Regex action. Otherwise
Modified: trunk/Catalyst-Runtime/lib/Catalyst.pm
===================================================================
--- trunk/Catalyst-Runtime/lib/Catalyst.pm 2007-03-29 02:53:04 UTC (rev 6231)
+++ trunk/Catalyst-Runtime/lib/Catalyst.pm 2007-03-29 02:58:01 UTC (rev 6232)
@@ -19,6 +19,8 @@
use Path::Class::File ();
use Time::HiRes qw/gettimeofday tv_interval/;
use URI ();
+use URI::http;
+use URI::https;
use Scalar::Util qw/weaken blessed/;
use Tree::Simple qw/use_weak_refs/;
use Tree::Simple::Visitor::FindByUID;
Modified: trunk/Catalyst-Runtime/t/live_engine_request_parameters.t
===================================================================
--- trunk/Catalyst-Runtime/t/live_engine_request_parameters.t 2007-03-29 02:53:04 UTC (rev 6231)
+++ trunk/Catalyst-Runtime/t/live_engine_request_parameters.t 2007-03-29 02:58:01 UTC (rev 6232)
@@ -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