Как я могу получить порт, который выбирает Mojolicious::Lite?

Джоэл Бергер опубликовал эту небольшую программу для начала веб-сервер для обслуживания локальных файлов, и он прекрасно работает:

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, если смогу. Поскольку старые вещи все еще работают, это действительно то, что приятно иметь, а не что-то на моем пути.


person brian d foy    schedule 30.03.2013    source источник
comment
Было бы полезно, если бы вы разместили код, из которого вы пытаетесь получить номер порта, чтобы мы могли видеть, что вы ожидаете от mojolicious раскрыть и как.   -  person Tudor Constantin    schedule 01.04.2013
comment
Там весь код. Я хочу запустить этот скрипт и узнать номер порта. Шри отвечает, что это всегда 3000 или ничего.   -  person brian d foy    schedule 02.04.2013
comment
это было бы легко проверить: попытка запустить 2 экземпляра приложения параллельно дает ошибку Can't create listen socket: Address already in use at ... - это показывает, что по умолчанию используется единственный пробный порт   -  person Tudor Constantin    schedule 02.04.2013
comment
Многие вещи кажутся легкими задним числом.   -  person brian d foy    schedule 03.04.2013


Ответы (2)


Вы не можете, но команда 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;
person Sebastian Riedel    schedule 01.04.2013
comment
Хорошо, приятно знать. На самом деле я не создаю приложение Mojo. Я использую очень легкий сервер для проверки загрузки некоторых статических файлов для кода веб-клиента. - person brian d foy; 02.04.2013

С параметром --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;

Мне нравится тестировать Mojolicious приложений с Test::Mojo, потому что вы получаете доступ к запущенному приложению, например, в файле 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();

Я не уверен, что правильно понял, чего вы пытаетесь достичь, но я надеюсь, что это поможет вам.

person Tudor Constantin    schedule 31.03.2013
comment
Я специально сказал, что не хочу выбирать порт. Я не хочу делать работу, чтобы найти открытый порт. Кроме того, доступ к веб-серверу для получения порта означает, что мне не нужно выяснять, что такое порт. - person brian d foy; 01.04.2013
comment
Хм ... точка зрения ОП о том, что вы не хотите вручную выбирать порт ... может быть, использовать генератор случайных чисел и проверить целевой порт, и если он не используется, назначьте его? - person lilHar; 28.08.2020