perlplack

How to handle errors in plack delayed response


Tried to handle errors in delayed response.

Every time i send [200, [ 'Content-Type', 'application/json' ] and got error before flushing the other things like that

$w->write("MyData");

$w->close();

i've got a warning in stdout and error in stderr, but page keeps loading.

it'll be loading until i stop app or stop page loading by hand.

how i can stop loading page in code or how to correctly handle errors in such apps where i use delayed response?

Perl version 5.24 Kelp version 1.02 Running Plack with Corona.

We're handling error throwing Exception::Class. Catching errors with Try::Tiny.

Also tried eval and others things, but it doesn't work. But changed Try::Tiny -> TryCatc and return if got any error, but i need write return for every catch block, it looks very bad

#!/usr/bin/perl
use strict;
use warnings;

use Kelp::Less;
get '/hello' => sub  {
    return sub {
        my $res = shift;
        my $w = $res->([200, [ 'Content-Type', 'application/json' ]]);
        my $data = 10 / 0;
        $w->write("MyData");
        $w->close();
    }
};
run;

I'm looking for correct error handling, do i need try{} catch{}; on every code that might fail?

Thanks @ikegami for answer, but page still loading after tries with Object::Destoyer and Sub::ScopeFinalizer. As i understand $w(writer) doesn't cause page loading. After exiting scope, $w comes undef then there's nothing to close, here is code.

#!/usr/bin/perl
use strict;
use warnings;

use Object::Destroyer;
use Kelp::Less;
get '/hello' => sub  {
    return sub {
        my $res = shift;

        my $w = $res->([200, [ 'Content-Type', 'application/json' ]]);
        my $g = Object::Destroyer->new( sub { $w->close if $w } );
        my $zzz = 1 / 0;
        $w->write("DATA");
        $w->close();
    }
};
run;

so i've come up with that solution, what do you think?

#!/usr/bin/perl
use strict;
use warnings;

use Try::Tiny;
use Object::Destroyer;
use Kelp::Less;
get '/hello' => sub  {
    return sub {
        my $res = shift;

        my $w = $res->([200, [ 'Content-Type', 'application/json' ]]);
        my $g = Object::Destroyer->new( sub { $w->close if $w; } );
        my $ans = try {                                                                   
            my $zzz = 1 / 0;                                                              
        }                                                                                 
        catch {
            print $_;                                                                   
            return;                                                                       
        };                                                                                
        return unless $ans;

        $w->write("DATA");
        $w->close();
    }
};
run;

Solution

  • Solve this problem with wrapping app with

    Plack::Middleware::HTTPExceptions