【问题标题】:How can I get the port that Mojolicious::Lite chooses?如何获取 Mojolicious::Lite 选择的端口?
【发布时间】:2013-03-20 18:07:40
【问题描述】:

Joel Berger posted this little program to start a web server to serve local files,效果很好:

use Mojolicious::Lite;

@ARGV = qw(daemon);

use Cwd;
app->static->paths->[0] = getcwd;

any '/' => sub {
    shift->render_static('index.html');
    };

app->start;

我在@ARGV 中预先填充了命令行,因为我忘了这样做。当它启动时,它会给出一条消息,告诉你它选择了哪个端口,如果可以的话,使用 3000:

$ perl ~/bin/mojo_cwd
[Fri Mar 29 19:14:09 2013] [info] Listening at "http://*:3000".
Server available at http://127.0.0.1:3000.

我想以编程方式获取该端口,以便测试套件知道在哪里寻找它,而且我不希望通过废弃输出来做到这一点。我对此的任何实验都没有用,我认为我总是走错方向。它似乎在启动之前不会选择端口,一旦我调用start,它就结束了。

我也不想自己指定端口。

这不是一件紧急的事情。我目前有一个使用另一个简单的 HTTP 框架的解决方案,但如果可以的话,我一直在考虑用 Mojo 替换其中的大部分内容。由于旧的东西仍然有效,这真的只是一件好事,而不是我的方式。

【问题讨论】:

  • 如果您发布您试图从中获取端口号的代码将会很有帮助 - 这样我们就可以看到您期望 mojolicious 公开什么以及如何公开。
  • 所有代码都在那里。我想运行该脚本并知道端口号。 sri 的回答是总是 3000 或者什么都没有。
  • 这很容易测试:尝试并行启动 2 个应用程序实例会出现错误 Can't create listen socket: Address already in use at ... - 这表明默认端口是唯一尝试过的端口
  • 事后看来很多事情都很容易。

标签: perl mojolicious


【解决方案1】:

您不能,但daemon 命令仅绑定到端口 3000,除非您告诉它,否则不会尝试其他任何操作。如果您使用的是Test::Mojo,则无论如何都不需要提前知道端口,对于其他任何事情,您始终可以将您的应用程序包装在一个小的Mojo::Server::Daemon 脚本中。

use Mojolicious::Lite;
use Mojo::IOLoop;
use Mojo::Server::Daemon;

get '/' => {text => 'Hello World!'};

my $port   = Mojo::IOLoop->generate_port;
my $daemon = Mojo::Server::Daemon->new(
  app    => app,
  listen => ["http://*:$port"]
);
$daemon->run;

【讨论】:

  • 好的,很高兴知道。我并没有真正创建 Mojo 应用程序。我正在使用一个非常轻量级的服务器来测试为 Web 客户端代码获取一些静态文件。
【解决方案2】:

使用--listen 参数,您可以为应用指定收听位置:

use Mojolicious::Lite;

@ARGV = qw(daemon --listen http://*:5000);

use Cwd;
app->static->paths->[0] = getcwd;

any '/' => sub {
    shift->render_static('index.html');
    };

app->start;

您可以通过$self->tx->local_port访问应用内的端口号:

#!/usr/bin/env perl
use Mojolicious::Lite;

@ARGV = qw(daemon --listen http://*:5000);

use Cwd;
app->static->paths->[0] = getcwd;

any '/' => sub {
    my $self = shift;

    $self->render_text('port: '. $self->tx->local_port);
    };

app->start if $ENV{MOJO_MODE} ne 'test';

1;

我喜欢用Test::Mojo 测试Mojolicious 应用程序,因为您可以访问正在运行的应用程序,例如,在文件t/test_mojo.t 中:

use strict;
use warnings;

use feature 'say';

use Test::More;
use Test::Mojo;

$ENV{MOJO_MODE} = 'test';

require "$FindBin::Bin/../test_mojo.pl";

my $t = Test::Mojo->new;
$t->get_ok('/')->status_is(200)->content_is('port: '.$t->tx->remote_port);

say 'local port: '. $t->tx->local_port; #as seen from the user-agent's perspective
say 'remote port:'. $t->tx->remote_port;
done_testing();

我不确定我是否正确理解了您要完成的工作,但我希望这对您有所帮助。

【讨论】:

  • 我特意说了不想选择端口。我不想做找到开放端口的工作。另外,访问网络服务器来获取端口意味着我不需要找出端口是什么。
  • 嗯......关于不想手动选择端口的OP的观点......也许使用随机数生成器,并测试目标端口,如果它没有被使用,分配那个?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-18
  • 2015-09-23
  • 1970-01-01
  • 2011-10-25
  • 2017-02-25
  • 1970-01-01
相关资源
最近更新 更多