diff --git a/Changes b/Changes index d6ed34817..18f1c25ea 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,7 @@ [ BUG FIXES ] * PR #1247: Fix edge case in plugin compat (Sawyer X) + * GH #1621: Fix recursion error in TT after longjump (Andy Beverley) * PR #1667: Remove failing module from GitHub Actions config (Jason A. Crome) diff --git a/lib/Dancer2/Core/App.pm b/lib/Dancer2/Core/App.pm index af1147040..2af2f88ce 100644 --- a/lib/Dancer2/Core/App.pm +++ b/lib/Dancer2/Core/App.pm @@ -884,6 +884,19 @@ sub template { and $self->setup_session; # return content + if ($self->has_with_return) { + my $old_with_return = $self->with_return; + my $local_response; + $self->set_with_return( sub { + $local_response ||= shift; + }); + my $content = $template->process( @_ ); + $self->set_with_return($old_with_return); + if ($local_response) { + $self->with_return->($local_response); + } + return $content; + } return $template->process( @_ ); } diff --git a/t/issues/gh-1621/gh-1621.t b/t/issues/gh-1621/gh-1621.t new file mode 100644 index 000000000..a079becf0 --- /dev/null +++ b/t/issues/gh-1621/gh-1621.t @@ -0,0 +1,52 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Test::More; +use Plack::Test; +use HTTP::Request::Common; +use Ref::Util qw; + +# Test to ensure that a longjump out of a template, caused by a call to redirect, +# does not cause any future problems rendering a template. Whilst this test is +# slightly obscure for reasons of simplicity, the exact use-case is in the use +# of Plugin::LogReport. If it catches a fatal error (which could occur during +# the render of a template) then it will redirect to another page. + +{ + package MyApp; + + use Dancer2; + + set template => 'template_toolkit'; + + # Set up 2 routes to the same template. The first route will redirect when + # the template renders, the second will not + get '/redirect' => sub { + my $redir = sub { + redirect "somewhere"; + }; + template 'redirect', + { redirect_sub => $redir } + }; + + get '/noredirect' => sub { + template 'redirect'; + }; +} + +my $app = Dancer2->psgi_app; +ok( is_coderef($app), 'Got app' ); + +test_psgi $app, sub { + my $cb = shift; + my $res = $cb->(GET '/redirect'); + is $res->code, 302, 'Redirect template results in redirect'; + + $res = $cb->(GET '/noredirect'); + is $res->code, 200, 'Successful subsequent request to normal template'; + like $res->content, qr/foobar/, 'Correct content'; +}; + +done_testing(); diff --git a/t/issues/gh-1621/views/redirect.tt b/t/issues/gh-1621/views/redirect.tt new file mode 100644 index 000000000..fcb9f613e --- /dev/null +++ b/t/issues/gh-1621/views/redirect.tt @@ -0,0 +1 @@ +[% IF NOT redirect_sub %]foobar[% END %]