perlweb-servicesroutesmojoliciousmojolicious-lite

Perl Mojolicious routes call sub only once


Iam using Mojolicious::Lite to declare routes for a webservice. Maybe i missunderstood the routes behaviour but if iam calling a subroutine in the routes definition it gets only called once.
I thougt the sub should get triggered every time the webservice route is called... which isn't the case.

For example i wrote a test route:

use Mojolicious::Lite;

get '/test' => {
    text => get_test()
};

sub get_test {
    say 'Hello iam only showing up once';

    return 'test';
};

This is the console output on starting the server and visiting the localhost:3000/test route:

Hello iam only showing up once
[2020-04-04 22:07:21.09011] [69050] [info] Listening at "http://*:3000"
Server available at http://127.0.0.1:3000
[2020-04-04 22:07:28.26033] [69050] [debug] [78278b87] GET "/test"
[2020-04-04 22:07:28.26097] [69050] [debug] [78278b87] 200 OK (0.000626s, 1597.444/s)

The "Hello iam only showing up once" is outputted once as the server starts. Visiting the route is not triggering the sub again.
If this is the wanted behaviour how can i get my routes to triggering the sub everytime the route is visited?

I need this because i use this webservice in my application to scan the network and return the result. And i want to rescan the network everytime i call the webservice GET route. Otherwise the data would be useless if its not up to date.

Thanks for your help and explanations.


Solution

  • Your code isn't actually rendering. Your get sub needs to call the render method from Mojolicious::Controller. Inside the get sub, $_[0] is an instance of the controller. In a Mojolicious::Lite app, the route and controller are combined, so you do need to render. If you change your code to this, it will do what you might expect.

    use Mojolicious::Lite;
    
    get '/test' => sub {
        shift()->render(text => get_test());
    };
    
    sub get_test {
        warn "Hello I show up on every hit.\n";
    
        return 'test';
    };
    

    The key difference is the shift()->render(...) call, which could also be written like this:

    get '/test' => sub {
        my $c = shift;
        $c->render(text => get_text());
    }