如何在Mojolicious应用程序中从命令行获取凭据?

smi*_*ith 7 perl mojolicious

我正在开发一个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处理此用例的最佳策略是什么?

sim*_*que 8

我将为这个问题提供两种解决方案.一个是相当容易的,而另一个使用一些先进的技术.

简单:使用环境变量

您可以在启动时将环境变量简单地传递给应用程序.

$ 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方式.它要求runSUPER::伪类.您可以在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.它还有很多代码.