Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plack::App::Cascade expects the $respond_wrapper to be called immediately #613

Open
ufobat opened this issue Feb 28, 2018 · 0 comments
Open

Comments

@ufobat
Copy link

ufobat commented Feb 28, 2018

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);
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant