我正在开发一个Mojolcious独立应用程序。在代码中,我正在联系内部后端,用户应在其中提供一些凭据。
目前我使用代码中的凭据作为变量。它看起来像是:
$password = 'somthing';
我尝试使用配置插件在那里存储凭据,但是Mojolicious是否有一个选项让用户在运行守护进程时提供他的凭据?也许像:
perl myapp.pl daemon -user username -password password
Mojolicious处理此用例的最佳策略是什么?
答案 0 :(得分:8)
我将为这个问题提供两种解决方案。一个是相当容易的,而另一个使用一些先进的技术。
您可以在启动时将环境变量简单地传递给您的应用。
$ USERNAME=foo PASSWORD=bar perl app.pl daemon
Mojolicious是Perl,所以他们最终进入%ENV
。我们可以使用$ENV{USERNAME}
和$ENV{PASSWORD}
访问它们。通常,这些环境变量是全部大写的。选择特定于应用的内容是有意义的,因此MYAPP_USERNAME
可能是比USERNAME
更好的选择。
关于这一点的好处是你也可以在shell环境中设置它,然后你就不必担心它。
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;
在上面的示例中,我创建了一个helper
来保存我们的凭据,以便于访问它们。当然,您可以在整个代码中使用$ENV{USERNAME}
,但我相信正确封装它会更好。
如果我们curl localhost:3000
守护进程,我们得到了这个输出。
$ curl localhost:3000
\ {
password "bar",
username "foo"
}
daemon
命令命令行参数全部由Mojolicious::Command处理。
您可以创建自己的Mojolicious :: Command子类。这在Mojolicious::Cookbook中有记录。如果将其命名为Mojolicious::Command::foo
,那么您甚至不必担心为Mojo添加另一个命名空间来查找命令。
但遗憾的是,你不能同时传递几个命令。因此,创建子类credentials
然后执行此操作不起作用。
$ perl myapp.pl daemon credentials --username foo --password bar
所以我们需要做点别的事。快速查看Mojolicious::Command::daemon告诉我们它只有run
方法,当调用该命令时会自动调用该方法。我们希望它做一些额外的事情,所以我们将该特定命令子类化。
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;
}
我们需要导入getopt
,这有助于我们从命令行中读取内容。我们将用户名和密码存储在credentials
帮助器中,就像第一种方法一样,因为封装很好。
最后,我们需要切换到原始的run
方法。这是通过调用$self->SUPER::run
完成的,这是Perl在我继承的我的超类上说调用run
的方式。它在run
伪类上调用SUPER::
。您可以在perlobj中了解有关详情。
现在实际的应用程序几乎相同。
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;
我们这样运行:
$ perl code/scratch.pl mydaemon --username foo --password bar
如果我们curl localhost:3000
得到相同的输出。
$ curl localhost:3000
\ {
password "bar",
username "foo"
}
您选择哪种方式取决于您。我不确定自己喜欢哪一个。两者都有优点。
环境变量更易于实现且更易于移植,但代码并不那么清晰。命令子类可以在正确完成时记录自己,但也许您的用户不会期望除daemon
之外的其他内容。它还有更多的代码。