Недавно я начал баловаться с Mojolicious, чтобы выполнить sh то, что изначально считал простой задачей.
Я взаимодействую с некоторыми устройствами VoIP, которые могут взаимодействовать с внешними веб-серверами, хотя и в довольно ограниченный и запутанный способ.
Мой wi sh должен публиковать sh информацию о текущем абоненте на телефонах VoIP, извлекая данные из базы данных наших клиентов. К сожалению, это не так просто, как можно было бы надеяться. Телефон должен получить веб-страницу в моем веб-приложении, которая, в свою очередь, должна запросить у телефона информацию о его состоянии вызова. Эта информация будет отправлена телефоном по фиксированному пути на веб-сервере. Эта информация о вызовах будет использоваться для извлечения дополнительных данных из базы данных, с помощью которой будет отображаться ответ на первый GET по телефону. Чрезмерно сложный, но единственный способ, которым я могу придумать, учитывая ограничения устройств.
И вот мы подошли к моим проблемам с Mojolicious. Я должен предупредить, что по профессии я системный администратор, и обычно мое кодирование не затрагивает серверные процессы, особенно асинхронное / неблокирующее программирование.
После дня экспериментов я пришел к выводу, что для двух маршрутов обработчики (правильная терминология?), сначала запрашиваемые телефоном, а те, к которым телефон передает свой статус вызова, для связи мне понадобится какой-то брокер сообщений. Я выбрал Mercury с помощью веб-сокетов, поскольку не хотел развертывать систему базы данных только для этой цели.
У меня нет проблем с выполнением обычных запросов POST / GET из обработчика маршрута, но когда я пытаюсь не блокируя веб-сокеты для целей публикации / подписки, я получаю «преждевременное закрытие соединения» и после дальнейшей отладки я вижу, что соединение с внешним сервером веб-сокетов вообще не выполняется.
post '/callinfo' => sub {
my $c = shift;
$c->inactivity_timeout(0);
my $ua = Mojo::UserAgent->new;
my $remote_url = 'ws://127.0.0.1:4000/pub/'. $c->tx->remote_address;
$ua->websocket( $remote_url => ['v2.proto', 'v1.proto'] => sub {
my ($ua, $tx) = @_;
say 'WebSocket handshake failed!' and return unless $tx->is_websocket;
$tx->on(finish => sub {
my ($tx, $code, $reason) = @_;
say "WebSocket closed with status $code.";
});
$tx->on(message => sub {
my ($tx, $msg) = @_;
say "WebSocket message: $msg";
$tx->finish;
});
$tx->send('Hi!');
}
);
}
Код выше это мой обработчик маршрутов, на данный момент довольно много стандартного кода из документации Mojolicious.
Я свободно признаюсь, что был не в своей тарелке, поэтому не могу понять, почему все идет не так, как я ожидаю. Я включил все параметры отладки, которые смог найти, но я думаю, что проблема должна заключаться в некотором фундаментальном непонимании того, как все это работает.
Что более удивительно, так это то, что в другом обработчике у меня аналогичное соединение с веб-сокетом, которое приходит после (хотя оба они неблокирующие, поэтому я не знаю, много ли в этом порядке) HTTP-вызова GET. И там это работает. Но если я комментирую вызов, выполняющий GET, я получаю ту же ошибку, но фактического соединения не происходит.
Итак ... я в замешательстве. Кто-нибудь имеет представление о причине и / или что я мог сделать, чтобы обойти проблему?
Не стесняйтесь исправлять меня в терминологии и основных недоразумениях. Это мой первый опыт такого рода программирования и, в частности, Mojolicious. К сожалению, я не могу найти достаточно проектов или фактического кода, чтобы черпать вдохновение, и документация немного скудна.