Search code examples
perlurl-routingmojolicious

Custom 404 route not matching website root


I have a few routes defined for my Mojolicious app and a catch-all 404 route:

$r->any('*')->to(cb => sub {
    my $self = shift;
    $self->render(text => '404 Not Found');
    $self->rendered(404);
});

The 404 route works fine:

$ ./bin/myapp.pl -m production get /no_such_url
404 Not Found

But I also want the 404 route to match the website root, and I always get some default Mojolicious 404 instead, even in production mode:

$ ./bin/myapp.pl -m production get /
<!DOCTYPE html>
<html>
  <head><title>Page not found</title></head>
…

What do I need to do to serve my plain 404 callback on /?


Solution

  • You are correct that any '*' will not catch the main index /. That appears to be the one exception. There are two easy solutions:

    You can just create an alias to your route. Note how we set the rendered code before we set the rendered text:

    use Mojolicious::Lite;
    
    sub my404 {
        my $self = shift;
        $self->rendered(404);
        $self->render(text => '404 any *');
    
    }
    
    any '*' => \&my404;
    any '/' => \&my404;
    
    app->start;
    

    You can also just override the default 404 not found template as documented in Rendering exception and not found pages:

    use Mojolicious::Lite;
    
    app->start;
    
    __DATA__
    
    @@ not_found.development.html.ep
    404 default template