Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mojolicious - how to intercept the incoming request before controller method handles and renders

In Mojolicious app, I need to figure out which controller method will be handling the incoming request so that I can log details of the remote client and add some logic. I want to do it at only one place and not in every controller methods. I have tried some of the HOOKS but could not figure out. Much appreciate any help on this.

Routes are generated/created from several OpenApi Plugin files and also use Oauth2 Plugin for OAuth.

  • Mojolicious detail:
CORE
  Perl        (v5.16.3, linux)
  Mojolicious (8.22, Supervillain)

OPTIONAL
  Cpanel::JSON::XS 4.04+  (n/a)
  EV 4.0+                 (4.22)
  IO::Socket::Socks 0.64+ (n/a)
  IO::Socket::SSL 2.009+  (2.060)
  Net::DNS::Native 0.15+  (n/a)
  Role::Tiny 2.000001+    (2.000005)

like image 679
Sachin Dangol Avatar asked Sep 17 '19 11:09

Sachin Dangol


People also ask

What is intercepting a request?

Sort of "intercepting" a request before it is handled by the controller, and only then letting the controller handle it.

What are the different use cases for MVC handler interceptors?

Let’s go over some of the different use cases that could come up when using MVC handler interceptors. One of the things you might want to do is retrieve a header from the incoming request to perform some type of validation. The request object (of type HttpServletRequest) contains a method called getHeader.

How do I create a handler interceptor in Java?

Any time you create a handler interceptor there will be two key components involved: In order for you to create a handler interceptor, you will need to create a class that extends the HandlerInterceptorAdapter class. This class will let you override two methods which are the preHandle and postHandle methods.

What is the point of parsing incoming requests in a controller?

The idea is that EVERY (!) incoming request is parsed and its contents get decoded without the programmer of the rest controller getting having to care about this at all. They should just access data via/from the MyClass instance.


1 Answers

I asked in mojolicious mailing list and got the reply from the creator of the Mojolicious, Sebastian Riedel. Thanks.

For everybody's benifit. $c->match->stack in around_action hook has the info I was looking for.

Here is how:

In your application startup method:

sub startup {
    my $self = shift;
    ...
        $self->hook(
            around_action => sub {
                my ($next, $c, $action, $last) = @_;
                use DDP;
                p $c->match; 
                # prints all the info about the controller and the method/action
                # it is going to call
                ...
            }
        );
    ...
}

DDP - Output

Mojolicious::Routes::Match  {
    Parents       Mojo::Base
    public methods (7) : endpoint, find, has, path_for, position, root, stack
    private methods (1) : _match
    internals: {
        endpoint   Mojolicious::Routes::Route,
        position   0,
        root       Mojolicious::Routes,
        stack      [
            [0] {
                action               "controller_method_name",
                controller           "ControllerClassName",
                handler              "openapi",
                id                   3336,
                openapi.object       Mojolicious::Plugin::OpenAPI,
                openapi.op_path      [
                    [0] "paths",
                    [1] "/api/endpoint/path/{id}/status",
                    [2] "get"
                ],
                openapi.parameters   [
                    [0] {
                        description   "job id",
                        in            "path",
                        name          "id",
                        required      JSON::PP::Boolean,
                        type          "number"
                    }
                ]
            }
        ]
    }
}

Here is the info I am looking for in $c->match->stack:

               action               "controller_method_name",
               controller           "ControllerClassName",
like image 139
Sachin Dangol Avatar answered Sep 28 '22 04:09

Sachin Dangol