aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml8
-rw-r--r--Gemfile.lock8
-rw-r--r--README.md6
-rw-r--r--gemfiles/Gemfile.rails-4-2 (renamed from gemfiles/rails_42.gemfile)0
-rw-r--r--lib/action_cable/channel/base.rb23
-rw-r--r--lib/action_cable/channel/callbacks.rb37
-rw-r--r--lib/action_cable/channel/periodic_timers.rb6
-rw-r--r--lib/action_cable/connection/base.rb11
-rw-r--r--test/channel/base_test.rb4
-rw-r--r--test/connection/authorization_test.rb12
10 files changed, 65 insertions, 50 deletions
diff --git a/.travis.yml b/.travis.yml
index 5e156e2b77..ff7376b9e5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,11 +8,15 @@ rvm:
gemfile:
- Gemfile
- - gemfiles/rails_4-2-stable.gemfile
+ - gemfiles/Gemfile.rails-4-2
matrix:
fast_finish: true
- allow_failures: ruby-head
+ allow_failures:
+ - ruby-head
+
+services:
+ - redis-server
notifications:
email: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 7f128bbdd1..3b67b1f67d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,6 +1,6 @@
GIT
remote: git://github.com/rack/rack.git
- revision: 6216a3f8a3560639ee1ddadc1e0d6bf9e5f31830
+ revision: 35599cfc2751e0ee611c0ff799924b8e7fe0c0b4
specs:
rack (2.0.0.alpha)
json
@@ -13,7 +13,7 @@ GIT
GIT
remote: git://github.com/rails/rails.git
- revision: 960de47f0eef79d234eb3cfc47fabb470fef1529
+ revision: f94e328cf801fd5c8055b06c4ee5439273146833
specs:
actionpack (5.0.0.alpha)
actionview (= 5.0.0.alpha)
@@ -59,7 +59,7 @@ GEM
remote: https://rubygems.org/
specs:
builder (3.2.2)
- celluloid (0.16.1)
+ celluloid (0.16.0)
timers (~> 4.0.0)
coffee-rails (4.1.0)
coffee-script (>= 2.2.0)
@@ -92,7 +92,7 @@ GEM
metaclass (~> 0.0.1)
nokogiri (1.6.6.2)
mini_portile (~> 0.6.0)
- puma (2.12.2)
+ puma (2.14.0)
rack-test (0.6.3)
rack (>= 1.0)
rails-deprecated_sanitizer (1.0.3)
diff --git a/README.md b/README.md
index 798ca5292f..94c40f079f 100644
--- a/README.md
+++ b/README.md
@@ -63,6 +63,8 @@ module ApplicationCable
end
end
```
+Here `identified_by` is a connection identifier that can be used to find the specific connection again or later.
+Note that anything marked as an identifier will automatically create a delegate by the same name on any channel instances created off the connection.
Then you should define your `ApplicationCable::Channel` class in Ruby. This is the place where you put
shared logic between your channels.
@@ -317,7 +319,7 @@ application. The recommended basic setup is as follows:
```ruby
# cable/config.ru
-require ::File.expand_path('../../config/environment', __FILE__)
+require ::File.expand_path('../../config/environment', __FILE__)
Rails.application.eager_load!
require 'action_cable/process/logging'
@@ -328,7 +330,7 @@ run ActionCable.server
Then you start the server using a binstub in bin/cable ala:
```
#!/bin/bash
-bundle exec puma -p 28080 cable/config.ru
+bundle exec puma -p 28080 cable/config.ru
```
The above will start a cable server on port 28080. Remember to point your client-side setup against that using something like:
diff --git a/gemfiles/rails_42.gemfile b/gemfiles/Gemfile.rails-4-2
index 8ca60d69db..8ca60d69db 100644
--- a/gemfiles/rails_42.gemfile
+++ b/gemfiles/Gemfile.rails-4-2
diff --git a/lib/action_cable/channel/base.rb b/lib/action_cable/channel/base.rb
index 31b8dece4a..67b312e5ea 100644
--- a/lib/action_cable/channel/base.rb
+++ b/lib/action_cable/channel/base.rb
@@ -76,10 +76,7 @@ module ActionCable
SUBSCRIPTION_CONFIRMATION_INTERNAL_MESSAGE = 'confirm_subscription'.freeze
SUBSCRIPTION_REJECTION_INTERNAL_MESSAGE = 'reject_subscription'.freeze
- on_subscribe :subscribed
- on_unsubscribe :unsubscribed
-
- attr_reader :params, :connection, :identifier
+ attr_reader :params, :connection, ::identifier
delegate :logger, to: :connection
class << self
@@ -147,7 +144,9 @@ module ActionCable
# Called by the cable connection when its cut so the channel has a chance to cleanup with callbacks.
# This method is not intended to be called directly by the user. Instead, overwrite the #unsubscribed callback.
def unsubscribe_from_channel
- run_unsubscribe_callbacks
+ run_callbacks :unsubscribe do
+ unsubscribed
+ end
end
@@ -202,7 +201,9 @@ module ActionCable
def subscribe_to_channel
- run_subscribe_callbacks
+ run_callbacks :subscribe do
+ subscribed
+ end
if subscription_rejected?
reject_subscription
@@ -238,19 +239,10 @@ module ActionCable
end
end
- def run_subscribe_callbacks
- self.class.on_subscribe_callbacks.each { |callback| send(callback) }
- end
-
- def run_unsubscribe_callbacks
- self.class.on_unsubscribe_callbacks.each { |callback| send(callback) }
- end
-
def transmit_subscription_confirmation
unless subscription_confirmation_sent?
logger.info "#{self.class.name} is transmitting the subscription confirmation"
connection.transmit ActiveSupport::JSON.encode(identifier: @identifier, type: SUBSCRIPTION_CONFIRMATION_INTERNAL_MESSAGE)
-
@subscription_confirmation_sent = true
end
end
@@ -264,7 +256,6 @@ module ActionCable
logger.info "#{self.class.name} is transmitting the subscription rejection"
connection.transmit ActiveSupport::JSON.encode(identifier: @identifier, type: SUBSCRIPTION_REJECTION_INTERNAL_MESSAGE)
end
-
end
end
end
diff --git a/lib/action_cable/channel/callbacks.rb b/lib/action_cable/channel/callbacks.rb
index dcdd27b9a7..295d750e86 100644
--- a/lib/action_cable/channel/callbacks.rb
+++ b/lib/action_cable/channel/callbacks.rb
@@ -1,28 +1,35 @@
+require 'active_support/callbacks'
+
module ActionCable
module Channel
module Callbacks
- extend ActiveSupport::Concern
+ extend ActiveSupport::Concern
+ include ActiveSupport::Callbacks
included do
- class_attribute :on_subscribe_callbacks, :on_unsubscribe_callbacks, instance_reader: false
-
- self.on_subscribe_callbacks = []
- self.on_unsubscribe_callbacks = []
+ define_callbacks :subscribe
+ define_callbacks :unsubscribe
end
- module ClassMethods
- # Name methods that should be called when the channel is subscribed to.
- # (These methods should be private, so they're not callable by the user).
- def on_subscribe(*methods)
- self.on_subscribe_callbacks += methods
+ class_methods do
+ def before_subscribe(*methods, &block)
+ set_callback(:subscribe, :before, *methods, &block)
+ end
+
+ def after_subscribe(*methods, &block)
+ set_callback(:subscribe, :after, *methods, &block)
+ end
+ alias_method :on_subscribe, :after_subscribe
+
+ def before_unsubscribe(*methods, &block)
+ set_callback(:unsubscribe, :before, *methods, &block)
end
- # Name methods that should be called when the channel is unsubscribed from.
- # (These methods should be private, so they're not callable by the user).
- def on_unsubscribe(*methods)
- self.on_unsubscribe_callbacks += methods
+ def after_unsubscribe(*methods, &block)
+ set_callback(:unsubscribe, :after, *methods, &block)
end
+ alias_method :on_unsubscribe, :after_unsubscribe
end
end
end
-end \ No newline at end of file
+end
diff --git a/lib/action_cable/channel/periodic_timers.rb b/lib/action_cable/channel/periodic_timers.rb
index 9bdcc87aa5..25fe8e5e54 100644
--- a/lib/action_cable/channel/periodic_timers.rb
+++ b/lib/action_cable/channel/periodic_timers.rb
@@ -7,8 +7,8 @@ module ActionCable
class_attribute :periodic_timers, instance_reader: false
self.periodic_timers = []
- on_subscribe :start_periodic_timers
- on_unsubscribe :stop_periodic_timers
+ after_subscribe :start_periodic_timers
+ after_unsubscribe :stop_periodic_timers
end
module ClassMethods
@@ -38,4 +38,4 @@ module ActionCable
end
end
end
-end \ No newline at end of file
+end
diff --git a/lib/action_cable/connection/base.rb b/lib/action_cable/connection/base.rb
index b3de4dd4a9..a988060d56 100644
--- a/lib/action_cable/connection/base.rb
+++ b/lib/action_cable/connection/base.rb
@@ -56,7 +56,7 @@ module ActionCable
def initialize(server, env)
@server, @env = server, env
- @logger = new_tagged_logger
+ @logger = new_tagged_logger || server.logger
@websocket = ActionCable::Connection::WebSocket.new(env)
@subscriptions = ActionCable::Connection::Subscriptions.new(self)
@@ -151,7 +151,6 @@ module ActionCable
server.add_connection(self)
rescue ActionCable::Connection::Authorization::UnauthorizedError
respond_to_invalid_request
- close
end
def on_message(message)
@@ -186,6 +185,8 @@ module ActionCable
end
def respond_to_invalid_request
+ close if websocket.alive?
+
logger.info finished_request_message
[ 404, { 'Content-Type' => 'text/plain' }, [ 'Page not found' ] ]
end
@@ -193,8 +194,10 @@ module ActionCable
# Tags are declared in the server but computed in the connection. This allows us per-connection tailored tags.
def new_tagged_logger
- TaggedLoggerProxy.new server.logger,
- tags: server.config.log_tags.map { |tag| tag.respond_to?(:call) ? tag.call(request) : tag.to_s.camelize }
+ if server.logger.respond_to?(:tagged)
+ TaggedLoggerProxy.new server.logger,
+ tags: server.config.log_tags.map { |tag| tag.respond_to?(:call) ? tag.call(request) : tag.to_s.camelize }
+ end
end
def started_request_message
diff --git a/test/channel/base_test.rb b/test/channel/base_test.rb
index 7eb8e15845..580338b44a 100644
--- a/test/channel/base_test.rb
+++ b/test/channel/base_test.rb
@@ -20,8 +20,8 @@ class ActionCable::Channel::BaseTest < ActiveSupport::TestCase
class ChatChannel < BasicChannel
attr_reader :room, :last_action
- on_subscribe :toggle_subscribed
- on_unsubscribe :toggle_subscribed
+ after_subscribe :toggle_subscribed
+ after_unsubscribe :toggle_subscribed
def initialize(*)
@subscribed = false
diff --git a/test/connection/authorization_test.rb b/test/connection/authorization_test.rb
index 762c90fbbc..68668b2835 100644
--- a/test/connection/authorization_test.rb
+++ b/test/connection/authorization_test.rb
@@ -8,17 +8,25 @@ class ActionCable::Connection::AuthorizationTest < ActionCable::TestCase
def connect
reject_unauthorized_connection
end
+
+ def send_async(method, *args)
+ # Bypass Celluloid
+ send method, *args
+ end
end
test "unauthorized connection" do
run_in_eventmachine do
server = TestServer.new
- env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket'
+ server.config.allowed_request_origins = %w( http://rubyonrails.com )
+
+ env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket',
+ 'HTTP_ORIGIN' => 'http://rubyonrails.com'
connection = Connection.new(server, env)
connection.websocket.expects(:close)
+
connection.process
- connection.send :on_open
end
end
end