I will provide two solutions to this problem. One of them is quite simple, while the other uses several advanced methods.
Easy: use environment variables
You can simply pass environment variables to your application when it starts.
$ USERNAME=foo PASSWORD=bar perl app.pl daemon
Mojolicious is Perl, so they end in %ENV
. We can access them using $ENV{USERNAME}
and $ENV{PASSWORD}
. Usually these environment variables are all-caps. It would be wise to choose something specific to the application, so MYAPP_USERNAME
is probably a better choice than USERNAME
.
It's good that you can also install it in your shell environment, and then you never have to worry about it.
package MyApp; use Mojolicious::Lite; use Data::Printer; helper( credentials => sub { state $credentials = { username => $ENV{USERNAME}, password => $ENV{PASSWORD}, } } ); get '/' => sub { my $c = shift; $c->render( text => np $c->app->credentials ); }; app->start;
In the above example, I created a helper
that stores credentials for us, so itβs easy to access them. Of course, you could just use $ENV{USERNAME}
in the whole code, but I think it's better to encapsulate it correctly.
If we curl localhost:3000
daemon, we get this result.
$ curl localhost:3000 \ { password "bar", username "foo" }
Optional: subclass daemon
Command
All command line arguments are processed by Mojolicious :: Command .
You can create your own subclass of Mojolicious :: Command. This is described in the Mojolicious :: Cookbook . If you call it Mojolicious::Command::foo
, you donβt even have to worry about adding another namespace for Mojo to search for commands.
But you can, unfortunately, not send several commands at the same time. So, create a subclass of credentials
, and then it will not work.
$ perl myapp.pl daemon credentials --username foo --password bar
So we need to do something else. A quick look at Mojolicious :: Command :: daemon tells us that it has only the run
method, which is automatically called when this command is called. We want him to do something extra, so we will subclass this specific command.
package Mojolicious::Command::mydaemon; use Mojo::Base 'Mojolicious::Command::daemon'; use Mojo::Util 'getopt'; sub run { my ( $self, @args ) = @_; getopt 'u|username=s' => \my $username, 'p|password=s' => \my $password; $self->app->credentials->{username} = $username; $self->app->credentials->{password} = $password; return $self->SUPER::run; }
We need to import getopt
, which helps us read stuff from the command line. We store the username and password in the credentials
helper, as in the first approach, because encapsulation is good.
Finally, we need to pass the original run
method. This is done by calling $self->SUPER::run
, which is the Perl way to call call run
my superclass from which I inherited. It calls run
in the pseudo-class SUPER::
. You can learn more about this at perlobj .
Now the actual application is almost the same.
package MyApp; use Mojolicious::Lite; use Data::Printer; helper( credentials => sub { state $credentials = { username => q{}, password => q{}, }; } ); get '/' => sub { my $c = shift; $c->render( text => np $c->app->credentials ); }; app->start;
We run it as follows:
$ perl code/scratch.pl mydaemon --username foo --password bar
And if we curl localhost:3000
we get the same result.
$ curl localhost:3000 \ { password "bar", username "foo" }
Which of these methods you choose is up to you. I'm not sure which one I would prefer myself. Both have their merits.
Environment variables are easier to implement and more portable, but the code is not so clear. A subclass of the command can document itself when everything is done correctly, but perhaps your users would not expect anything other than daemon
. This is also a lot more code.