Skip to content

Commit

Permalink
fix URI construction when PATH_INFO contains URI reserved characters …
Browse files Browse the repository at this point in the history
…such as ? or #. Fixes plackgh-118
  • Loading branch information
miyagawa committed Jul 3, 2010
1 parent 45c4479 commit a01c607
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
11 changes: 10 additions & 1 deletion lib/Plack/Request.pm
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,16 @@ sub uri {

my $base = $self->_uri_base;

my $path = $self->env->{PATH_INFO} || '';
# We have to escape back PATH_INFO in case they include stuff like
# ? or # so that the URI parser won't be tricked. However we should
# preserve '/' since encoding them into %2f doesn't make sense.
# This means when a request like /foo%2fbar comes in, we recognize
# it as /foo/bar which is not ideal, but that's how the PSGI PATH_INFO
# spec goes and we can't do anything about it. See PSGI::FAQ for details.
# http://github.com/miyagawa/Plack/issues#issue/118
my $path_escape_class = '^A-Za-z0-9\-\._~/';

my $path = URI::Escape::uri_escape($self->env->{PATH_INFO} || '', $path_escape_class);
$path .= '?' . $self->env->{QUERY_STRING}
if defined $self->env->{QUERY_STRING} && $self->env->{QUERY_STRING} ne '';

Expand Down
30 changes: 30 additions & 0 deletions t/Plack-Request/path_info_escaped.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use strict;
use Test::More;
use Plack::Test;
use Plack::Request;
use HTTP::Request::Common;
use Data::Dumper;

my $path_app = sub {
my $req = Plack::Request->new(shift);
my $res = $req->new_response(200);
$res->content_type('text/plain');
$res->content('my ' . Dumper([ $req->uri, $req->parameters ]));
return $res->finalize;
};

test_psgi $path_app, sub {
my $cb = shift;

my $res = $cb->(GET "http://localhost/foo.bar-baz?a=b");
is_deeply eval($res->content), [ URI->new("http://localhost/foo.bar-baz?a=b"), { a => 'b' } ];

$res = $cb->(GET "http://localhost/foo%2fbar#ab");
is_deeply eval($res->content), [ URI->new("http://localhost/foo/bar"), {} ],
"%2f vs / can't be distinguished - that's alright";

$res = $cb->(GET "http://localhost/%23foo?a=b");
is_deeply eval($res->content), [ URI->new("http://localhost/%23foo?a=b"), { a => 'b' } ];
};

done_testing;

0 comments on commit a01c607

Please sign in to comment.