【问题标题】:WebSockets: Can connect but cannot subscribe to channelWebSockets:可以连接但不能订阅频道
【发布时间】:2019-08-06 17:30:15
【问题描述】:

我有一个在 nginx 中运行的仅 Rails API 应用程序,有乘客。我正在尝试使用 Action Cable 在 Flutter 中设置一个简单的聊天应用程序,但我似乎无法让它正常工作。

我可以使用以下方式进行连接:

 channel = IOWebSocketChannel.connect("wss://my.domain/cable")

当发生这种情况时,请在我的 production.log 中查看以下内容:

Started GET "/cable" for [redacted] at 2019-03-14 19:44:09 +0000
Started GET "/cable" [WebSocket] for [redacted] at 2019-03-14 19:44:09 +0000
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: upgrade, HTTP_UPGRADE: websocket)
Doorkeeper::AccessToken Load (0.3ms)  SELECT  `oauth_access_tokens`.* FROM `oauth_access_tokens` WHERE `oauth_access_tokens`.`token` = '[redacted]' LIMIT 1
User Load (0.2ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
Registered connection (Z2lkOi8vYWdlbnQyNHg3L1VzZXIvMg)

所以连接似乎已经建立并成功升级

然后我发送一个订阅命令

channel.sink.add(json.encode({
  "command": "subscribe",
  "identifier": {"channel": "ConversationChannel", "conversation_id": "${conversation.id}"}
}));

我不确定执行此命令后是否应该在日志文件中看到任何内容,但我没有。没有任何反应,并且我的 production.log 或我的 nginx 错误日志中没有任何错误的迹象。我在 ConversationChannel 的 subscribe 方法中设置了一些日志记录,因此在调用它时它至少会向生产日志输出一些内容,因此我可以测试它是否至少调用了 subscribe 命令

class ConversationChannel < ApplicationCable::Channel
    def subscribed
      Rails.logger.info "test conversation subscribe"
      reject && return unless current_user
      stream_from "conversation_#{params[:conversation_id]}_channel"
    end

    ...

end

但这不会出现在 production.log 中,因此订阅命令似乎没有到达它应该去的地方。

然后我尝试使用位于here(来自a conversation on github regarding connection states)的代码使用 dart WebSocket,看看我是否可以确定连接是否恢复正常。

当我使用我的域运行该代码时,我在 production.log 中看到相同的成功连接,但连接实际上超时了 onerror TimeoutException after 0:00:15.000000: Future not completed,这似乎表明连接实际上没有 毕竟成功了,不管它在日志文件中说了什么。

我在这里做错了什么?

【问题讨论】:

  • 嗨,您找到解决方案了吗?
  • 不,我没有。我刚刚放弃了我的应用程序中打算支持的功能。我感觉这是某种服务器级别的配置问题,但我不知道是什么。我正在部署一个新的服务器设置,所以我计划在那里从头开始尝试。如果我最终找到了解决方案,我会更新我的问题让其他人知道。
  • 你可以使用action_cable 来处理flutter,也许这个code 可以帮你。

标签: ruby-on-rails nginx redis flutter actioncable


【解决方案1】:

如果我记得,当您尝试连接到频道时,您的标识符必须是 JSON 字符串化的,以及您的整个 JSON 对象。看看这个链接:

https://thoughtbot.com/blog/talking-to-actioncable-without-rails

特别是:

const msg = {
  command: 'subscribe',
  identifier: JSON.stringify({
    channel: 'SomeChannel',
  }),
};
socket.send(JSON.stringify(msg));

Rails 在后端完成整个 JSON 解析。看看这是否对你有帮助。我之前在尝试连接 WebSocket 时遇到过类似的问题,但没有使用它们的 ActionCable npm 库。

【讨论】:

  • 您好,感谢您抽出宝贵时间回复!是的,我已经在我看过的大多数教程中看到了这种方法。我最初尝试过没有成功,现在再次尝试了同样的成功水平。在我看来这也是错误的,因为在这些示例中它们实际上对标识符对象进行了两次编码 - 所以你最终得到 {"command":"subscribe","identifier":"{\"channel\":\"ConversationChannel\",\"conversation_id\":\"2\"}"} - 注意标识符部分是字符串转义的,但命令部分不是。如果我们获取结果字符串并尝试对其进行解码,则会失败。
  • @MarkRawlingson,您是否正确获取订阅方法中的会话 ID?
猜你喜欢
  • 2018-01-20
  • 1970-01-01
  • 1970-01-01
  • 2013-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-14
  • 2018-09-03
相关资源
最近更新 更多