mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Accept JSON with no backslashes/escaping
Fixes #22675 Allow channel identifiers and also data with no backslahes/escaping to be accepted by the subscription storer.
This commit is contained in:
parent
fc1b32f8d1
commit
45635098ac
4 changed files with 27 additions and 8 deletions
|
@ -1,3 +1,8 @@
|
|||
* Allow channel identifiers with no backslahes/escaping to be accepted
|
||||
by the subscription storer.
|
||||
|
||||
*Jon Moss*
|
||||
|
||||
* Safely support autoloading and class unloading, by preventing concurrent
|
||||
loads, and disconnecting all cables during reload.
|
||||
|
||||
|
|
|
@ -23,13 +23,13 @@ module ActionCable
|
|||
end
|
||||
|
||||
def add(data)
|
||||
id_key = data['identifier']
|
||||
id_options = ActiveSupport::JSON.decode(id_key).with_indifferent_access
|
||||
id_options = decode_hash(data['identifier'])
|
||||
identifier = normalize_identifier(id_options)
|
||||
|
||||
subscription_klass = connection.server.channel_classes[id_options[:channel]]
|
||||
|
||||
if subscription_klass
|
||||
subscriptions[id_key] ||= subscription_klass.new(connection, id_key, id_options)
|
||||
subscriptions[identifier] ||= subscription_klass.new(connection, identifier, id_options)
|
||||
else
|
||||
logger.error "Subscription class not found (#{data.inspect})"
|
||||
end
|
||||
|
@ -37,7 +37,7 @@ module ActionCable
|
|||
|
||||
def remove(data)
|
||||
logger.info "Unsubscribing from channel: #{data['identifier']}"
|
||||
remove_subscription subscriptions[data['identifier']]
|
||||
remove_subscription subscriptions[normalize_identifier(data['identifier'])]
|
||||
end
|
||||
|
||||
def remove_subscription(subscription)
|
||||
|
@ -46,7 +46,7 @@ module ActionCable
|
|||
end
|
||||
|
||||
def perform_action(data)
|
||||
find(data).perform_action ActiveSupport::JSON.decode(data['data'])
|
||||
find(data).perform_action(decode_hash(data['data']))
|
||||
end
|
||||
|
||||
def identifiers
|
||||
|
@ -63,8 +63,21 @@ module ActionCable
|
|||
private
|
||||
delegate :logger, to: :connection
|
||||
|
||||
def normalize_identifier(identifier)
|
||||
identifier = ActiveSupport::JSON.encode(identifier) if identifier.is_a?(Hash)
|
||||
identifier
|
||||
end
|
||||
|
||||
# If `data` is a Hash, this means that the original JSON
|
||||
# sent by the client had no backslashes in it, and does
|
||||
# not need to be decoded again.
|
||||
def decode_hash(data)
|
||||
data = ActiveSupport::JSON.decode(data) unless data.is_a?(Hash)
|
||||
data.with_indifferent_access
|
||||
end
|
||||
|
||||
def find(data)
|
||||
if subscription = subscriptions[data['identifier']]
|
||||
if subscription = subscriptions[normalize_identifier(data['identifier'])]
|
||||
subscription
|
||||
else
|
||||
raise "Unable to find subscription with identifier: #{data['identifier']}"
|
||||
|
|
|
@ -82,13 +82,13 @@ class ActionCable::Connection::SubscriptionsTest < ActionCable::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
test "unsubscrib from all" do
|
||||
test "unsubscribe from all" do
|
||||
run_in_eventmachine do
|
||||
setup_connection
|
||||
|
||||
channel1 = subscribe_to_chat_channel
|
||||
|
||||
channel2_id = ActiveSupport::JSON.encode(id: 2, channel: 'ActionCable::Connection::SubscriptionsTest::ChatChannel')
|
||||
channel2_id = ActiveSupport::JSON.encode({ id: 2, channel: 'ActionCable::Connection::SubscriptionsTest::ChatChannel' })
|
||||
channel2 = subscribe_to_chat_channel(channel2_id)
|
||||
|
||||
channel1.expects(:unsubscribe_from_channel)
|
||||
|
|
|
@ -6,6 +6,7 @@ require 'puma'
|
|||
require 'mocha/setup'
|
||||
|
||||
require 'rack/mock'
|
||||
require 'active_support/core_ext/hash/indifferent_access'
|
||||
|
||||
# Require all the stubs and models
|
||||
Dir[File.dirname(__FILE__) + '/stubs/*.rb'].each {|file| require file }
|
||||
|
|
Loading…
Reference in a new issue