Returning a Json Error page on exception and not found

1,335 views
Skip to first unread message

marcos rebelo

unread,
Apr 21, 2011, 2:32:26 AM4/21/11
to mojol...@googlegroups.com
Hy all

I'm using Mojolicious for my JSON web-service. In the Documentation I
found the solution for returning customized HTML error page in one of
exception and not found, but since my application has a JSON
interface, I would like to return some customized JSON on this cases.

How do I do this?

Thanks for any help

Best Regards
Marcos

--
Marcos Rebelo
http://www.oleber.com/
Milan Perl Mongers leader https://sites.google.com/site/milanperlmongers/
Webmaster of http://perl5notebook.oleber.com

Анатолий Шарифулин

unread,
Apr 21, 2011, 2:40:18 AM4/21/11
to mojol...@googlegroups.com
You can try to use json format as default format in your application.

On Thursday, April 21, 2011, marcos rebelo <ole...@gmail.com> wrote:
> Hy all
>
> I'm using Mojolicious for my JSON web-service. In the Documentation I
> found the solution for returning customized HTML error page in one of
> exception and not found, but since my application has a JSON
> interface, I would like to return some customized JSON on this cases.
>
> How do I do this?
>
> Thanks for any help
>
> Best Regards
> Marcos
>
> --
> Marcos Rebelo
> http://www.oleber.com/

> Milan Perl Mongers leader milanperlmongers <https://sites.google.com/site/milanperlmongers/>
> Webmaster of http://perl5notebook.oleber.com
>
> --
> You received this message because you are subscribed to the Google Groups "Mojolicious" group.
> To post to this group, send email to mojol...@googlegroups.com.
> To unsubscribe from this group, send email to mojolicious...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/mojolicious?hl=en.
>
>

--
С уважением,
Анатолий Шарифулин.

marcos rebelo

unread,
Apr 21, 2011, 3:29:33 AM4/21/11
to mojol...@googlegroups.com

Sebastian Riedel

unread,
Apr 21, 2011, 8:42:08 AM4/21/11
to mojol...@googlegroups.com
Error pages are currently HTML only i'm afraid, you have to overload render_exception in your controller for something else.

--
Sebastian Riedel
http://mojolicio.us
http://twitter.com/kraih
http://blog.kraih.com

marcos rebelo

unread,
Apr 21, 2011, 9:01:28 AM4/21/11
to mojol...@googlegroups.com
Sebastian, I tried that one didn't work.

The exception page is done by some other method, doesn't passes on
that Controller method.

Best Regards
Marcos

Brian Duggan

unread,
Apr 21, 2011, 9:55:22 AM4/21/11
to mojol...@googlegroups.com
On Thursday, April 21, marcos rebelo wrote:
> On Thu, Apr 21, 2011 at 14:42, Sebastian Riedel <kra...@googlemail.com> wrote:
> > Error pages are currently HTML only i'm afraid, you have to overload render_exception in your controller for something else.
> Sebastian, I tried that one didn't work.
>
> The exception page is done by some other method, doesn't passes on
> that Controller method.

I recently found myself doing things like this :

$Mojolicious::Controller::EXCEPTION =
Mojo::Command->new->get_data( 'exception.html.ep',
"My::Controller::Class" );

It would be nice if these were attributes rather
than package variables, so they could be overridden.
Here's a potential patch :

https://gist.github.com/gists/934522

Brian

Sebastian Riedel

unread,
Apr 21, 2011, 10:03:19 AM4/21/11
to mojol...@googlegroups.com
Don't like the patch at all, you're supposed to overload the methods, not the default templates.
The real problem seems to be that render_exception from the default controller gets used instead of the current controller.

Brian Duggan

unread,
Apr 21, 2011, 10:34:22 AM4/21/11
to mojol...@googlegroups.com
On Thursday, April 21, Sebastian Riedel wrote:
> Don't like the patch at all, you're supposed to overload the methods, not the default templates.

Oh, well. Actually, I was doing both (and calling $self->SUPER::render_not_found
in my render_not_found). I suppose I could just move everything into the
derived class.

For some context, I'm not using this technique in a particular application,
but rather in a sub-framework used by a few applications. So, it is just
providing new defaults.

Brian

Sebastian Riedel

unread,
Apr 21, 2011, 11:53:03 AM4/21/11
to mojol...@googlegroups.com
Ok, there was a bug that prevented controller specific "render_exception" methods, it should be fixed now. https://github.com/kraih/mojo/compare/69fbd6807611ec209eff4147b511c8c324a80118...d9145abedbbebe226f9f6f3b22488de88809ba4d

"render_not_found" is a lot more complicated though since there is the possibility of routes to action-less templates.
Suggestions for how to handle this better or even patches would be very welcome.
(Just remember that there has to be a deprecation path for backwards compatibility breaking changes)

sri

unread,
Apr 21, 2011, 12:10:38 PM4/21/11
to Mojolicious
> Oh, well.  Actually, I was doing both (and calling $self->SUPER::render_not_found
> in my render_not_found).  I suppose I could just move everything into the
> derived class.
>
> For some context, I'm not using this technique in a particular application,
> but rather in a sub-framework used by a few applications.  So, it is just
> providing new defaults.

I see, but why not just have your own "exception.html.ep" template in
an actual file or the DATA section?
That's what puzzled me a bit about the patch.

--
sebastian

marcos rebelo

unread,
Apr 21, 2011, 12:25:05 PM4/21/11
to mojol...@googlegroups.com

The subject of this email is "Returning a Json Error page on exception
and not found", this means returning a application/json media type,
probably my HTTP-Status, ...

The render exception gives the full liberty/responsibility to the
programmer to decide how to correctly handle the exceptions and the
not found.

Best Regards
Marcos Rebelo

> --
> sebastian


>
> --
> You received this message because you are subscribed to the Google Groups "Mojolicious" group.
> To post to this group, send email to mojol...@googlegroups.com.
> To unsubscribe from this group, send email to mojolicious...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/mojolicious?hl=en.
>
>

--

Brian Duggan

unread,
Apr 21, 2011, 12:28:01 PM4/21/11
to mojol...@googlegroups.com
On Thursday, April 21, sri wrote:
> > For some context, I'm not using this technique in a particular application,
> > but rather in a sub-framework used by a few applications. �So, it is just
> > providing new defaults.
>
> I see, but why not just have your own "exception.html.ep" template in
> an actual file or the DATA section?

I do have it in a DATA section, but it looks like Mojolicious::Controller
only looks in the DATA section for Mojolicious::Controller, not in
the DATA section for a derived class.

Brian


sri

unread,
Apr 21, 2011, 12:40:01 PM4/21/11
to Mojolicious
> I do have it in a DATA section, but it looks like Mojolicious::Controller
> only looks in the DATA section for Mojolicious::Controller, not in
> the DATA section for a derived class.

You can just put whatever class you like into the "template_class"
stash value, the renderer will pick it up and look for templates
there.

$self->stash(template_class => __PACKAGE__);

or just

$self->render('foo', format => 'xml', template_class =>
__PACKAGE__);

--
sebastian

sri

unread,
Apr 21, 2011, 12:49:44 PM4/21/11
to Mojolicious
Almost forgot one.

app->renderer->default_template_class('MyApp::Foo');

Since you most likely won't need custom exception templates in the
DATA section of every single controller.

P.S.: Generally i would suggest plain old templates in actual files
for normal Mojolicious apps though, the whole DATA section embedding
process has originally been designed for Mojolicious::Lite single file
prototypes.

--
sebastian

Brian Duggan

unread,
Apr 21, 2011, 2:01:59 PM4/21/11
to mojol...@googlegroups.com
On Thursday, April 21, sri wrote:
> app->renderer->default_template_class('MyApp::Foo');

Works perfectly, thanks!

Brian

marcos rebelo

unread,
Apr 21, 2011, 3:02:19 PM4/21/11
to mojol...@googlegroups.com
With all the respect Brian Duggan, I did this question and until now I
didn't get my answer. I need to return JSON, with a correct
media-type.

How do I do this???

Thanks for all your help.

Best Regards
Marcos Rebelo

> --
> You received this message because you are subscribed to the Google Groups "Mojolicious" group.
> To post to this group, send email to mojol...@googlegroups.com.
> To unsubscribe from this group, send email to mojolicious...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/mojolicious?hl=en.
>
>

--

Abhijit Menon-Sen

unread,
Apr 21, 2011, 3:11:36 PM4/21/11
to mojol...@googlegroups.com
At 2011-04-21 21:02:19 +0200, ole...@gmail.com wrote:
>
> I need to return JSON, with a correct media-type.
>
> How do I do this???

$self->render_json({ message => "Help, I'm stuck!" });

-- ams

Brian Duggan

unread,
Apr 21, 2011, 4:08:32 PM4/21/11
to mojol...@googlegroups.com

And for errors, override the controller methods :

package My::Controller;
use base 'Mojolicious::Controller';

sub render_not_found {
shift->render_json({sorry => "not found"});
}

sub render_exception {
shift->render_json({somethings => "wrong"});
}

package main;
use Mojolicious::Lite;

app->controller_class("My::Controller");

...

Brian

sri

unread,
Apr 21, 2011, 7:53:29 PM4/21/11
to Mojolicious
And controller specific render_not_found methods work too now,
enjoy. :) https://github.com/kraih/mojo/commit/2f28c211733a894fa5539e76908a23f5dbb9b833

package MyApp::Foo;
use Mojo::Base 'Mojolicious::Controller';

sub bar { shift->render_json({hello => 'world!'}) }

sub render_exception { shift->render_json({error => 'server
error'}) }

sub render_not_found { shift->render_json({error => 'not found'}) }

1;

--
sebastian

Ben van Staveren

unread,
Apr 21, 2011, 9:22:28 PM4/21/11
to mojol...@googlegroups.com
sri++

--
Ben van Staveren
phone: +62 81 70777529
email: benvans...@gmail.com

marcos rebelo

unread,
May 2, 2011, 5:19:13 AM5/2/11
to mojol...@googlegroups.com
I went on holidays, Just returned today.

Thanks to all

Best Regards
Marcos Rebelo

Ilya Obshadko

unread,
May 23, 2013, 8:29:36 PM5/23/13
to mojol...@googlegroups.com, kra...@googlemail.com
Found this thread on the web. Custom render_exception method doesn't seem to work anymore.
Is that possible to re-enable this functionality? Thank you.

njzt

unread,
Apr 10, 2015, 8:07:28 AM4/10/15
to mojol...@googlegroups.com
I have quite similar case in  my JSON REST app. Using Mojolicious 5 I was overriding render_exception and render_not_found in my main Controller class. Here is a short version:

package MyApp::Controller;

use Mojo::Base 'Mojolicious::Controller';

# overwritten methods of Mojolicious::Controller
sub render_not_found {
  $c
->respond(404)  
}
sub render_exception {
 
# 1. store & send information about error
 
# 2. switch to special statuses eg. 408 & 503
 
# 3. provide more details to json_data_response
  $c
->respond($status)
}

sub render_not_authorized {
 
# prepare json_data_response of failed authorization
  $c
->respond(403)  
}


# common method to standarize output for different statuses & formats
sub respond {
# ...
  $c
->respond_to(
    json
=> sub { # 99% requests are json
      $c
->render(json => $c->json_data_response)
   
},
    html
=> sub {
      given
($status) {
       
when (404) { $c->SUPER::render_not_found() }
       
when (500) { $c->SUPER::render_exception() }
       
# more eg. 403, 400
     
}
   
}
 
)
}

Do you have any suggestion how can I easily migrate such solution to Mojolicious 6 where render_exception and render_not_found are no longer supported. I was thinking of overriding reply.exception and reply.not_found helpers. Any other ideas?

Jan Henning Thorsen

unread,
Apr 10, 2015, 8:19:31 AM4/10/15
to mojol...@googlegroups.com
I'm doing this:

  $self->hook(
    before_render => sub {
      return unless $_[0]->accepts('json');
      my ($c, $args) = @_;
      my $template = $args->{template} || '';

      if ($template =~ /^not_found/) {
        $args->{json} = {errors => [{path => '/', message => 'Resource not found.'}]};
      }
      elsif ($template =~ /^exception/) {
        $args->{json} = {errors => [{path => '/', message => $args->{exception} || 'Unknown error.'}]};
      }
    }
  );

Have a look here for more details:

njzt

unread,
Apr 13, 2015, 3:17:00 AM4/13/15
to mojol...@googlegroups.com
Thanks, I will try with that.

njzt

unread,
Apr 13, 2015, 6:07:49 AM4/13/15
to mojol...@googlegroups.com
I've made asap workaround that works with my old solution:

$self->helper('reply.exception_orig' => sub { # make clone of original reply.exception
  Mojolicious::Plugin::DefaultHelpers::_development('exception', @_)
});
$self->helper('reply.exception' => sub { # use customized MyApp::Controller::render_exception
  MyApp::Controller::render_exception(@_);
});



Reply all
Reply to author
Forward
0 new messages