我正在开发一个Mojolcious独立应用程序.在代码中,我正在联系内部后端,用户应在其中提供一些凭据.
目前我使用代码中的凭据作为变量.它看起来像是这样的:
$password = 'somthing';
Run Code Online (Sandbox Code Playgroud)
我尝试使用配置插件在那里存储凭据,但有一个Mojolicious选项让用户在运行守护进程时提供他的凭据吗?也许喜欢:
perl myapp.pl daemon -user username -password password
Run Code Online (Sandbox Code Playgroud)
Mojolicious处理此用例的最佳策略是什么?
我将为这个问题提供两种解决方案.一个是相当容易的,而另一个使用一些先进的技术.
您可以在启动时将环境变量简单地传递给应用程序.
$ USERNAME=foo PASSWORD=bar perl app.pl daemon
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,我创建了一个helper为我们保存凭据,因此很容易访问它们.当然,您可以在$ENV{USERNAME}整个代码中使用,但我相信将其正确封装更好.
如果我们curl localhost:3000守护进程,我们得到这个输出.
$ curl localhost:3000
\ {
password "bar",
username "foo"
}
Run Code Online (Sandbox Code Playgroud)
daemonCommand命令行参数全部由Mojolicious :: Command处理.
您可以创建自己的Mojolicious :: Command子类.这在Mojolicious :: Cookbook中有记载.如果你命名它,Mojolicious::Command::foo那么你甚至不必担心为Mojo添加另一个命名空间来查找命令.
但遗憾的是,你不能同时传递几个命令.所以创建一个子类credentials然后这样做是行不通的.
$ perl myapp.pl daemon credentials --username foo --password bar
Run Code Online (Sandbox Code Playgroud)
所以我们需要做点别的事.快速浏览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;
}
Run Code Online (Sandbox Code Playgroud)
我们需要导入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;
Run Code Online (Sandbox Code Playgroud)
我们这样运行:
$ perl code/scratch.pl mydaemon --username foo --password bar
Run Code Online (Sandbox Code Playgroud)
如果我们curl localhost:3000得到相同的输出.
$ curl localhost:3000
\ {
password "bar",
username "foo"
}
Run Code Online (Sandbox Code Playgroud)
您选择哪种方式取决于您.我不确定自己喜欢哪一个.两者都有优点.
环境变量更容易实现,更易于移植,但代码并不那么清晰.命令子类可以在正确完成时记录自己,但也许你的用户不会期望别的东西daemon.它还有很多代码.