Class: Rage::Cable::Protocols::RawWebSocketJson

Inherits:
Base
  • Object
show all
Defined in:
lib/rage/cable/protocols/raw_web_socket_json.rb

Overview

The RawWebSocketJson protocol allows a direct connection to a Rage::Cable application using the native WebSocket object. With this protocol, each WebSocket connection directly corresponds to a single channel subscription. As a result, clients are automatically subscribed to a channel as soon as they establish a connection.

Heartbeats are also supported - the server will respond with pong to every ping message. Additionally, all ping messages are buffered and processed once a second, which means it can take up to a second for the server to respond to a ping.

Examples:

Server side

class TodoItemsChannel
  def subscribed
    stream_from "todo-items-#{params[:user_id]}"
  end

  def receive(data)
    puts "New Todo item: #{data}"
  end
end

Client side

socket = new WebSocket("ws://localhost:3000/cable/todo_items?user_id=123")
socket.send(JSON.stringify({ item: "New Item" }))

See Also:

Class Method Summary collapse

Methods inherited from Base

broadcast, protocol_definition

Class Method Details

.init(router) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/rage/cable/protocols/raw_web_socket_json.rb', line 47

def self.init(router)
  super

  @ping_connections = Set.new

  Iodine.on_state(:on_start) do
    Iodine.run_every(1_000) do
      @ping_connections.each_slice(500) do |slice|
        Iodine.defer { slice.each { |connection| connection.write("pong") } }
      end

      @ping_connections.clear
    end
  end
end

.on_close(connection) ⇒ Object

Parameters:



120
121
122
# File 'lib/rage/cable/protocols/raw_web_socket_json.rb', line 120

def self.on_close(connection)
  @router.process_disconnection(connection)
end

.on_message(connection, raw_data) ⇒ Object

Parameters:



105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/rage/cable/protocols/raw_web_socket_json.rb', line 105

def self.on_message(connection, raw_data)
  if raw_data == "ping"
    @ping_connections << connection
    return
  end

  data = JSON.parse(raw_data)

  message_status = @router.process_message(connection, IDENTIFIER, :receive, data)
  unless message_status == :processed
    connection.write(MESSAGES::UNKNOWN)
  end
end

.on_open(connection) ⇒ Object

Parameters:



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/rage/cable/protocols/raw_web_socket_json.rb', line 64

def self.on_open(connection)
  accepted = @router.process_connection(connection)

  unless accepted
    connection.write(MESSAGES::UNAUTHORIZED)
    connection.close
    return
  end

  channel_id = connection.env["PATH_INFO"].split("/")[-1]

  channel_name = if channel_id.end_with?("Channel")
    channel_id
  else
    if channel_id.include?("_")
      tmp = ""
      channel_id.split("_") { |segment| tmp += segment.capitalize! || segment }
      channel_id = tmp
    else
      channel_id.capitalize!
    end

    "#{channel_id}Channel"
  end

  query_string = connection.env["QUERY_STRING"]
  params = query_string == "" ? DEFAULT_PARAMS : Iodine::Rack::Utils.parse_nested_query(query_string)

  status = @router.process_subscription(connection, IDENTIFIER, channel_name, params)

  if status == :rejected
    connection.write(MESSAGES::REJECTED)
    connection.close
  elsif status == :invalid
    connection.write(MESSAGES::INVALID)
    connection.close
  end
end

.serialize(_, data) ⇒ Object

Parameters:

  • data (Object)

    the object to serialize



125
126
127
# File 'lib/rage/cable/protocols/raw_web_socket_json.rb', line 125

def self.serialize(_, data)
  data.to_json
end

.supports_rpc?Boolean

Returns:

  • (Boolean)


130
131
132
# File 'lib/rage/cable/protocols/raw_web_socket_json.rb', line 130

def self.supports_rpc?
  false
end