PerlDancer / Dancer2

Perl Dancer Next Generation (rewrite of Perl Dancer)
http://perldancer.org/
Other
543 stars 273 forks source link

allow Dancer2 to work with HTTP::Throwable, et al. #1576

Closed clemep-sios closed 3 years ago

clemep-sios commented 3 years ago

Right now, if Dancer2 encounters an HTTP::Throwable, HTTP::Exception or similar, this gets caught by the response_internal_error routine in Dancer2::Core::App and translated to 500 Internal Server Error instead of passing the HTTP exception status code through.

This works fine in a pure plack/PSGI app, but not with a Dancer2 app.

(I can add an on_route_exception hook [see below] to circumvent the response_internal_error handling in Dancer2::Core::App, but it's kind of ugly.)

Test below illustrates:

#!/usr/bin/perl
use Test::More;
use Plack::Test;
use Plack::Builder;
use Plack::Middleware::PrettyException;
use Plack::Middleware::HTTPExceptions;
use HTTP::Request::Common;
use HTTP::Throwable::Factory qw(http_throw);

sub psgi_app {
    my $env = shift;
    if ($env->{PATH_INFO} eq '/api') {
        http_throw(NotAcceptable => {});
    } 
};

my $psgi_app = \&psgi_app;

package DancerApp {
        use HTTP::Throwable::Factory qw(http_throw);
        use Dancer2;

        ### I CAN ADD THIS REALLY HACKY HOOK IN TO MAKE THE TEST PASS??? 
        # hook on_route_exception => sub {
        #        my ($app, $error) = @_;
        #
        #        status $error->{'status_code'};
        #        halt;
        # };

        get '/api' => sub {
                http_throw(NotAcceptable => {});
        };
};

my $dancer_app = DancerApp->to_app;

my $plack_psgi = builder {
    enable "PrettyException" => ( force_json => 1 );
    enable "HTTPExceptions";
    $psgi_app
};

my $plack_dancer = builder {
    enable "PrettyException" => ( force_json => 1 );
    enable "HTTPExceptions";
    $dancer_app
};

# PSGI:
my $t = Plack::Test->create($plack_psgi);
my $r = $t->request(GET '/api');
is($r->code, 406, 'GET /api');
print "PSGI response 1: " . $r->message . " Content: " . $r->content . "\n";

# DANCER:
my $t2 = Plack::Test->create($plack_dancer);
my $r = $t2->request(GET '/api');
is($r->code, 406, 'GET /api');
print "DANCER response 1: " . $r->message . " Content: " . $r->content . "\n";

done_testing();