dispatching Mojolicious::Lite apps on Mojolicious/PSGI/Plack.

78 views
Skip to first unread message

長岡雄一郎

unread,
Dec 8, 2016, 2:17:28 AM12/8/16
to Mojolicious
I have an issue with dispatching Mojolicious::Lite apps on Mojolicious/PSGI/Plack.
Can someone help me please?

This is what I am trying:

----------
Mojolicious 7.11
Server-Starter-0.32
Starlet-0.30 #using one worker

#Mojolicious
use Mojo::Base 'Mojolicious';

sub startup {
    my $self = shift;
    $self->hook(
            before_routes => sub {
                my $controller_self = shift;

                # Get $status from database which value changes depending on the request URL.
                my $status = getStatusFromDB($controller_self->req->url->path);

                # Mounting this plugin in every request.
                $self->plugin('MyApp::Plugin::CustomizedApp',$status);
            }
    );
}
1;

#Mojolicious
package MyApp::Plugin::CustomizedApp;
use Mojo::Base 'Mojolicious::Plugin';

sub register {
    my ($self,$app, $status) = @_;

    if ( $status eq '01' ){
        $app->routes->any('/')->detour(
            app => foo::bar::bazForm::app()
        );
    }
    elsif( $status eq '02' ){
        $app->routes->any('/')->detour(
            app => foo::bar::quxForm::app()
        );
    }
    else{
        # handles error
    }
}
1;

#Mojolicious::Lite controller
package foo::bar::bazForm;
use Mojolicious::Lite;
use Mojo::Base 'Mojolicious::Controller';

any '/*' => sub {
    my $self = shift;
    return ($self->render(text => 'This is bazForm'));
};


#Mojolicious::Lite controller
package foo::bar::quxForm;
use Mojolicious::Lite;
use Mojo::Base 'Mojolicious::Controller';

any '/*' => sub {
    my $self = shift;
    return ($self->render(text => 'This is quxForm'));
};
----------

I want to change controllers depending on the $status, using the same URL route, but the
Starlet worker (or the Mojolicious app) seems to keep dispatching the first controller that was defined.

What I want:
First  access to URL => status is '02' => foo::bar::quxForm is dispatched
Second access to URL => status is '01' => foo::bar::bazForm is dispatched
Third  access to URL => status is '02' => foo::bar::quxForm is dispatched


What is happening:
First  access to URL => status is '02' => foo::bar::quxForm is dispatched
Second access to URL => status is '01' => foo::bar::quxForm is dispatched
Third  access to URL => status is '02' => foo::bar::quxForm is dispatched

note: When Mojolicious restarts, the worker seems to be initialized.The first access defines which controller the worker dispatches.

I've tried
using namespaces(doesn't seem to be using the one I defined),
"to" instead of "detour"(always 404 error),
Mojolicious instead of M::L controllers.

Brian Manning

unread,
Dec 8, 2016, 10:38:23 AM12/8/16
to Mojolicious


On Wednesday, December 7, 2016 at 11:17:28 PM UTC-8, Yuichiro wrote:
I want to change controllers depending on the $status, using the same URL route, but the
Starlet worker (or the Mojolicious app) seems to keep dispatching the first controller that was defined.

What you are actually doing is trying to change routes after your first request comes in, which is not possible [1] (without restarting your app).  This is why the controller that is servicing your requests is "sticky" (stays the same no matter what the status is) after the first request comes in.

You may want to use a single controller/action method for the URL, and in there route the request in that controller to another class dynamically based on the status from your database.

Thanks,

Brian

Yuichiro

unread,
Dec 16, 2016, 3:34:14 AM12/16/16
to Mojolicious
Thank you for your reply.

I'm going to use single controller/action method for the URL each case.
Reply all
Reply to author
Forward
0 new messages