Skip to content

Commit

Permalink
Use better method for localizing env in adapt_psgi
Browse files Browse the repository at this point in the history
  • Loading branch information
bbrtj committed Oct 10, 2024
1 parent 8b77084 commit 7ef6c5a
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 25 deletions.
21 changes: 10 additions & 11 deletions lib/Kelp/Util.pm
Original file line number Diff line number Diff line change
Expand Up @@ -138,17 +138,16 @@ sub adapt_psgi
$path =~ s{^/?}{/};
$path =~ s{/?$}{$trailing_slash};

# adjust script and path
$env->{SCRIPT_NAME} = $orig_path;
$env->{SCRIPT_NAME} =~ s{\Q$path\E$}{};
$env->{PATH_INFO} = $path;

# run the callback
my $result = $app->($env);

# restore old script and path
$env->{SCRIPT_NAME} = $orig_script;
$env->{PATH_INFO} = $orig_path;
my $result;
{
# adjust script and path
local $env->{SCRIPT_NAME} = $orig_path;
$env->{SCRIPT_NAME} =~ s{\Q$path\E$}{};
local $env->{PATH_INFO} = $path;

# run the callback
$result = $app->($env);
}

# produce a response
if (ref $result eq 'ARRAY') {
Expand Down
72 changes: 58 additions & 14 deletions t/psgi.t
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,39 @@ my $psgi_dumper = sub {
];
};

# this is a PSGI app which compares env keys
my $psgi_comparer = sub {
my $env = shift;

my %env_before = %$env;
my $res = Kelp->NEXT_APP->($env);

my $all_valid = 1;
foreach my $key (keys %env_before) {
my $value = $env_before{$key};
next if ref $value;

$all_valid &&= $value eq $env->{$key};
}

if (!$all_valid) {
push @{$res->[2]}, "BADENV\n";
}

return $res;
};

my $app = Kelp->new(mode => 'test');
$app->routes->fatal(1);

$app->add_route(
'/' => {
to => sub { 1 },
bridge => 1,
psgi_middleware => $psgi_comparer,
}
);

$app->add_route(
'/app1' => {
to => $psgi_dumper,
Expand Down Expand Up @@ -64,59 +94,72 @@ my $t = Kelp::Test->new(app => $app);
$t->request(GET "/app1")
->code_is(200)
->content_like(qr{^script: /app1$}m)
->content_like(qr{^path: $}m);
->content_like(qr{^path: $}m)
->content_unlike(qr{^BADENV$}m);

$t->request(GET "/app1/")
->code_is(200)
->content_like(qr{^script: /app1$}m)
->content_like(qr{^path: /$}m);
->content_like(qr{^path: /$}m)
->content_unlike(qr{^BADENV$}m);

$t->request(GET "/app1/x")
->code_is(404);
->code_is(404)
->content_unlike(qr{^BADENV$}m);

$t->request(GET "/app2")
->code_is(200)
->content_like(qr{^script: /app2$}m)
->content_like(qr{^path: $}m);
->content_like(qr{^path: $}m)
->content_unlike(qr{^BADENV$}m);

$t->request(GET "/app2/")
->code_is(200)
->content_like(qr{^script: /app2$}m)
->content_like(qr{^path: /$}m);
->content_like(qr{^path: /$}m)
->content_unlike(qr{^BADENV$}m);

$t->request(GET "/app2/x")
->code_is(200)
->content_like(qr{^script: /app2$}m)
->content_like(qr{^path: /x$}m);
->content_like(qr{^path: /x$}m)
->content_unlike(qr{^BADENV$}m);

$t->request(GET "/app2/x/")
->code_is(200)
->content_like(qr{^script: /app2$}m)
->content_like(qr{^path: /x/$}m);
->content_like(qr{^path: /x/$}m)
->content_unlike(qr{^BADENV$}m);

$t->request(GET "/app2/x/y")
->code_is(200)
->content_like(qr{^script: /app2$}m)
->content_like(qr{^path: /x/y$}m);
->content_like(qr{^path: /x/y$}m)
->content_unlike(qr{^BADENV$}m);

$t->request(GET "/app3")
->code_is(404);
->code_is(404)
->content_unlike(qr{^BADENV$}m);

$t->request(GET "/app3/")
->code_is(404);
->code_is(404)
->content_unlike(qr{^BADENV$}m);

$t->request(GET "/app3/x")
->code_is(200)
->content_like(qr{^script: /app3$}m)
->content_like(qr{^path: /x$}m);
->content_like(qr{^path: /x$}m)
->content_unlike(qr{^BADENV$}m);

$t->request(GET "/app3/x/")
->code_is(200)
->content_like(qr{^script: /app3$}m)
->content_like(qr{^path: /x/$}m);
->content_like(qr{^path: /x/$}m)
->content_unlike(qr{^BADENV$}m);

$t->request(GET "/app3/x/y")
->code_is(404);
->code_is(404)
->content_unlike(qr{^BADENV$}m);

# application unicode support should be distinct from Kelp. Kelp will just have
# to pass everything to the app through psgi env undecoded. App result should
Expand All @@ -139,7 +182,8 @@ subtest 'testing unicode' => sub {
->code_is(200)
->full_content_type_is('text/plain')
->content_like(qr{^script: /zażółć$}m)
->content_like(qr{^path: /gęślą/jaźń$}m);
->content_like(qr{^path: /gęślą/jaźń$}m)
->content_unlike(qr{^BADENV$}m);
};

done_testing;
Expand Down

0 comments on commit 7ef6c5a

Please sign in to comment.