首页 > 解决方案 > 无法从 Mojolicious 路由处理程序内部连接到外部 websocket

问题描述

我最近发现自己正在涉足 Mojolicious,以完成我最初认为是一项简单的任务。

我正在与一些可以与外部 Web 服务器交互的 VoIP 设备进行交互,尽管方式非常有限且复杂。

我希望将有关当前呼叫者的信息发布到 VoIP 电话,从我们的客户数据库中提取数据。不幸的是,这并不像人们希望的那样简单。电话应该在我的 Web 应用程序上获取一个网页,然后它应该查询电话以获取有关其呼叫状态的信息。该信息将通过电话发布到网络服务器上的固定路径。该呼叫信息将用于从数据库中提取其他数据,通过该数据将响应呈现给电话的第一个 GET。过于复杂,但鉴于设备的局限性,我能想到的唯一方法。

在这里,我们用 Mojolicious 来解决我的问题。我必须预先警告我是一名系统管理员,通常我的编码不会触及服务器进程,尤其是异步/非阻塞编程。

经过一天的实验,我得出的结论是,对于两个路由处理程序(正确的术语?),一个是最初由电话查询的,另一个是电话向其发送呼叫状态的,要进行通信,我需要某种消息经纪人。我选择了使用 websockets 的 Mercury,因为我不想仅仅为此目的部署数据库系统。

我从路由处理程序内部执行正常的 POST/GET 请求没有问题,但是当我尝试将非阻塞 websockets 用于发布/订阅目的时,我得到一个“过早的连接关闭”,并且从进一步调试中我看到与外部的连接websocket 服务器根本没有发生。

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 文档中的样板代码。

我坦率地承认在这里我很不适应,所以我无法弄清楚为什么事情没有像我预期的那样发展。我启用了我能找到的所有调试选项,但我想问题一定是对整个事情的工作原理缺乏理解。

更令人困惑的是,在另一个处理程序中,我有一个类似的 websocket 连接,它位于 HTTP GET 调用之后(尽管它们都是非阻塞的,所以我不知道该命令是否有太多意义)。它在那里工作。但是,如果我评论执行 GET 的调用,我会得到相同的错误,但没有发生实际连接。

所以......我很难过。有没有人知道原因和/或我可以做些什么来规避这个问题?

请随时纠正我的术语和核心误解。这是我第一次尝试这种编程,尤其是 Mojolicious。不幸的是,我找不到足够的项目或实际代码来从中汲取灵感,而且文档也有些稀缺。

标签: perlasynchronouswebsocketmojolicious

解决方案


推荐阅读