成功连接后,ActionCable.Connection状态未设置为“打开”,导致发送方法失败

时间:2018-07-24 20:35:49

标签: javascript ruby-on-rails websocket actioncable

有关环境的相关信息

  • 导轨版本:5.2
  • Devise身份验证

代码

用于设置Cookie的存储钩子

# config/initializers/warden_hooks.rb
Warden::Manager.after_set_user do |user,auth,opts|
  scope = opts[:scope]
  auth.cookies.signed["#{scope}.id"] = user.id
  auth.cookies.signed["#{scope}.expires_at"] = 30.minutes.from_now
end

Warden::Manager.before_logout do |user, auth, opts|
  scope = opts[:scope]
  auth.cookies.signed["#{scope}.id"] = nil
  auth.cookies.signed["#{scope}.expires_at"] = nil
end

用于认证的连接父类。这样可以正常工作并记录连接。

# application_cable/connection.rb
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
      logger.add_tags 'ActionCable', current_user.email
    end

    protected

    USER_CLASSES = ['admin', 'agent', 'tech', 'client']

    def find_verified_user
      user_class = USER_CLASSES.find { |klass| cookies.signed["#{klass}.id"] }
      user_id = cookies.signed["#{user_class}.id"]
      verified_user = User.find_by(id: user_id)

      if verified_user && cookies.signed["#{user_class}.expires_at"] > Time.now
        verified_user
      else
        reject_unauthorized_connection
      end
    end
  end
end

用于建立连接和发送消息的客户端代码。

// channels/conversations.js
$(document).on('turbolinks:load', function() {
  var messages = $('#messages');
  var projectId = messages.data('project-id');
  var button = $('#new_message input[type=submit]');
  var subscription = { channel: "ConversationsChannel", id: projectId };

  App.conversation = App.cable.subscriptions.create(subscription, {
    connected: function() {
      console.log('Upgraded to websocket connection.');
    },
    disconnected: function() {
      console.log('Websocket not connected.');
    },
    received: function(data) {
      messages.append(data['message']);
    },
    sendMessage: function(message, project_id) {
      return this.perform('send_message', {
        message: message,
        project_id: projectId
      });
    }
  });

  $('#message_body').on('keyup', function(e) {
    var message = e.target.value;

    if ($.trim(message).length > 0) {
      button.prop('disabled', false);
    } else {
      button.prop('disabled', true);
    }
  });

  $('#new_message').submit(function(e) {
    e.preventDefault();
    var textarea = $('#message_body');

    App.conversation.sendMessage(textarea.val(), projectId);

    textarea.val('');
    button.prop('disabled', true);
  });
});

问题

连接已在服务器上注册

enter image description here

,但是客户端上ActionCable.Connection的状态永远不会设置为打开,这会导致Connection.send方法失败,因为this.isOpen()返回false(因此,客户端永远不会订阅频道)-ActionCable source

如果我在send内的chrome中放置一个断点,并将数据传递给webSocket.send方法,则订阅成功。

enter image description here

enter image description here

如果要发送消息,我必须重复一遍,因为即使成功建立订阅后,连接状态仍未设置为打开。

我已经尝试过的东西

  • 认证所有人
  • 返回current_user中的Connection#connect
  • 从Connection类中删除所有代码,以便不覆盖任何行为

0 个答案:

没有答案