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

send_error do not setup response code for hook callbacks #1229

Open
KES777 opened this issue Jan 10, 2022 · 1 comment
Open

send_error do not setup response code for hook callbacks #1229

KES777 opened this issue Jan 10, 2022 · 1 comment

Comments

@KES777
Copy link
Contributor

KES777 commented Jan 10, 2022

When we call send_error 418, { some => 'error' }

Next code is executed:

  1>203: sub send_error      { Dancer::Continuation::Route::ErrorSent->new(
    204:                           return_value => Dancer::Error->new(
    205:                               message => $_[0],
    206:                               code => $_[1] || 500)->render()
    207:                       )->throw }

Then this error is rendered (see line 206)

    191: sub render {
   x192:     my $self = shift;
    193:
   x194:     
   x195:     my $serializer = setting('serializer');
   x196:     Dancer::Factory::Hook->instance->execute_hooks('before_error_render', $self);
   x197:     my $response;
    198:     try {
 b4>199:         $response = $serializer ? $self->_render_serialized() : $self->_render_html();
    200:     } continuation {
 b x201:         my ($continuation) = @_;
    202:         # If we have a Route continuation, run the after hook, then
    203:         # propagate the continuation
   x204:         Dancer::Factory::Hook->instance->execute_hooks('after_error_render', $response);
   x205:         $continuation->rethrow();
  7>206:     };
 b x207:     Dancer::Factory::Hook->instance->execute_hooks('after_error_render', $response);
   x208:     $response;
    209: }

Here next subs are executed: before_error_render, _render_serialized

_render_serialized calls Dancer::Serializer->engine->serialize($message) in turn.

    211: sub _render_serialized {
   x212:     my $self = shift;
    213:
   x214:     
   x215:     my $message =
    216:       !ref $self->message ? {error => $self->message} : $self->message;
    217:
   x218:     if (ref $message eq 'HASH' && defined $self->exception) {
   x219:         if (blessed($self->exception)) {
   x220:             $message->{exception} = ref($self->exception);
   x221:             $message->{exception} =~ s/^Dancer::Exception:://;
    222:         } else {
   x223:             $message->{exception} = $self->exception;
    224:         }
    225:     }
    226:
   x227:     if (setting('show_errors')) {
  3>228:         Dancer::Response->new(
    229:             status  => $self->code, # <<< not in sync with Dancer::status # 200 != 418
    230:             content => Dancer::Serializer->engine->serialize($message),
    231:             headers => ['Content-Type' => Dancer::Serializer->engine->content_type]
    232:             );
    233:     }

both before_error_render and serialize are application subroutines, which may refer to Dancer::SharedData->response.
But this object is not in sync with http_code passed to send_error: 418 != 200

@KES777
Copy link
Contributor Author

KES777 commented Jan 10, 2022

How to reproduce this:

Dancer::status 201;
send_error 418, { some => 'error' }

It will be in sync only after init:

/opt/perl5lib/lib/perl5/Dancer/Error.pm
   x227:     if (setting('show_errors')) {
  2>228:         Dancer::Response->new(
    229:             status  => $self->code,
    230:             content => Dancer::Serializer->engine->serialize($message),
    231:             headers => ['Content-Type' => Dancer::Serializer->engine->content_type]
    232:             );
    233:     }

/opt/perl5lib/lib/perl5/Dancer/Object.pm
    14: sub new {
   x15:     my ($class, %args) = @_;
   x16:     my $self = \%args;
   x17:     bless $self, $class;
  1>18:     $self->init(%args);
   x19:     return $self;
    20: }

/opt/perl5lib/lib/perl5/Dancer/Response.pm
    22: sub init {
  >>23:     my ( $self, %args ) = @_;
   x24:     $self->attributes_defaults(
    25:         status  => 200,
    26:         content => '',
    27:         pass    => 0,
    28:         halted  => 0,
    29:         forward => '',
    30:         encoded => 0,
    31:     );
   x32:     $self->{headers} = HTTP::Headers->new(@{ $args{headers} || [] });
               # at this point $self->code != Dancer::status # 418 != 201
   x33:     Dancer::SharedData->response($self);
    34: }

Probably we need to update Dancer::SharedData->response before hooks are called.

@KES777 KES777 changed the title send_error do not setup response code send_error do not setup response code for hook callbacks Jan 10, 2022
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