given the example plack app using lots of middleware components and an mojolicious app enabled in builder (see below), how can i pass parameters from the app.psgi to Mojolicious without using the ugly %ENV hack shown? of cause passing an config is just an example, this could be any scalar/object.
app.psgi
use Plack::Builder;
$ENV{CONFIG} = {...};
builder {
...
Mojolicious::Commands->start_app('MyApp');
};
MyApp.pm
package MyApp;
use Mojo::Base 'Mojolicious';
sub startup {
my $self = shift;
my $r = $self->routes;
$self->config( $ENV{CONFIG} );
$r->route('/')->to('home#');
}
This is an interesting question and is most easily tackled by looking at the source. In your example you rightly use
Mojolicious::Commands->start_app('MyApp');
Looking at the source shows that start_app
is a rather simple wrapper:
sub start_app {
my $self = shift;
return Mojo::Server->new->build_app(shift)->start(@_);
}
It turns out that build_app
is as well:
sub build_app {
my ($self, $app) = @_;
local $ENV{MOJO_EXE};
return $app->new unless my $e = Mojo::Loader->new->load($app);
die ref $e ? $e : qq{Couldn't find application class "$app".\n};
}
returning a new instance of your app's class. The Mojolicious class's new
function is more involved, but in the end, it just calls the familiar startup
method and returns the instance.
This means that you cannot easily pass arguments to the startup
method from your middleware wrapper, used in the standard way. I can think of two mechanisms to accomplish what you want to do: 1) write your own build_app
function to replace the server's method but which passes arguments to $app->new
(which would get passed to startup
in turn) or 2) write your own start_app
function which could call another startup
-like function.
# in MyApp.pm
sub startup {
... # as before
}
sub after_startup {
... # your new code here,
# or even most of what was in `startup` before
}
and
# app.psgi
builder {
...
my $app = Mojo::Server->new->build_app(shift);
$app->after_startup(@your_args_here);
$app->start(@_);
}