Plack::App::Cascade expects the $respond_wrapper to be called immediately
ufobat opened this issue · 0 comments
ufobat commented
Hi,
I've been working with an async PSGI server. And i've been running into troubles with Plack::App::Cascade
. I am not sure but I think that using $done
(https://github.com/plack/Plack/blob/master/lib/Plack/App/Cascade.pm#L58) within the iteration is not correct. Because it requires that $respond_wrapped
is called immediatly (https://github.com/plack/Plack/blob/master/lib/Plack/App/Cascade.pm#L54) and I think the spec is not requireing this, right? At least my Async PSGI implementation is not calling it immediately, but waits till the Application has fulfilled the request.
IMHO Cascade.pm needs to wait until the application is really done with the request. This is my "hack" that might solve this issue:
sub call {
my($self, $env) = @_;
return sub {
my $respond = shift;
my @try = @{$self->apps || []};
my $tries_left = 0 + @try;
my $respond_wrapper = sub {
my $res = shift;
if ($self->codes->{$res->[0]}) {
# suppress output by giving the app an
# output spool which drops everything on the floor
$self->call_next_app(\@try, $env, __SUB__, $respond);
return Plack::Util::inline_object
write => sub { }, close => sub { };
} else {
return $respond->($res);
}
};
if (not $tries_left) {
return $respond->([ 404, [ 'Content-Type' => 'text/html' ], [ '404 Not Found' ] ])
}
$self->call_next_app(\@try, $env, $respond_wrapper, $respond);
};
}
sub call_next_app {
my $self = shift;
my $try = shift;
my $env = shift;
my $respond_wrapper = shift;
my $respond = shift;
my $app = shift @$try;
return unless $app;
my $res = $app->($env);
unless (@$try) {
$respond_wrapper = sub { $respond->(shift) };
}
if (ref $res eq 'CODE') {
$res->($respond_wrapper);
} else {
$respond_wrapper->($res);
}
}