Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create common handler for all incoming URLs?

I'm in process of writing some web api, which returns data in JSON format.

For all incoming urls i need to return some result from cache if cache period doesnt expire.

This logic is universal for all URLs.

Question:

How to implement some common logic for all incoming URLs in Mojolicious::Lite?

I tried to do

any '/:bar' => [bar => qr/.+/] => sub {
 # ...
 # Return JSON object immediately from cache if it is applicable
 # ...
}

But this leads to very long page loading and

Template "bar.html.ep" not found

in morbo log (but get "/target" handler will be executed finally, after very long delay).

I am a perfect newbie in Mojo, so any help will be appreciated

Thanks!

like image 480
drvtiny Avatar asked Oct 19 '22 00:10

drvtiny


2 Answers

Yes, a before_dispatch hook seems like the right approach, and it does work with Mojolicious::Lite. Here's a proof-of-concept that will produce a new result for each unique request, but return repeat results for repeated requests. In this program, the regular request handler populates the cache, but if you wanted to separate that part from the main functions of your code you could do the caching in an after_dispatch hook.

use Mojolicious::Lite;

our %CACHE;

any '/:any' => sub {
    my $self = shift;
    my $param = $self->param('any');
    my $result = { reqtime => time, param => $param, number => rand };
    my $path = $self->req->url->path->to_string;
    $CACHE{$path} //= $result;
    $self->render( json => $result );
};

app->hook( before_dispatch => sub {
    my $c = shift;
    my $path = $c->req->url->path->to_string;
    if (defined($CACHE{$path})) {
        $c->render( json => $CACHE{$path}, status => 200 );
    }
} );
app->secrets([42])->start;

Sample run:

$ morbo cachedemo.pl >/dev/null 2>&1 &

$ for req in foo foo1 foo2 foo3 foo foo1
> do curl http://localhost:3000/$req ; echo ; sleep 1 ; done

{"number":0.848003210075227,"reqtime":1444254617,"param":"foo"}
{"number":0.0745738560703799,"reqtime":1444254618,"param":"foo1"}
{"number":0.484934245556467,"reqtime":1444254619,"param":"foo2"}
{"number":0.181112856445004,"reqtime":1444254620,"param":"foo3"}
{"number":0.848003210075227,"reqtime":1444254617,"param":"foo"}     <-- dup
{"number":0.0745738560703799,"reqtime":1444254618,"param":"foo1"}   <-- dup
like image 160
mob Avatar answered Oct 22 '22 21:10

mob


you can use * placeholder. Look here

Also put you application into developer mode:

Mojolicious->new( mode => 'developer' );
$app->mode( 'developer');

You will get pretty 404, 500 pages that will help you very much

like image 45
Eugen Konkov Avatar answered Oct 22 '22 22:10

Eugen Konkov