aboutsummaryrefslogtreecommitdiffstats
path: root/actioncable
diff options
context:
space:
mode:
Diffstat (limited to 'actioncable')
-rw-r--r--actioncable/README.md27
-rw-r--r--actioncable/lib/action_cable/connection/base.rb20
-rw-r--r--actioncable/lib/action_cable/server/broadcasting.rb2
3 files changed, 31 insertions, 18 deletions
diff --git a/actioncable/README.md b/actioncable/README.md
index 6e74551483..c85d59a1c8 100644
--- a/actioncable/README.md
+++ b/actioncable/README.md
@@ -17,7 +17,7 @@ The client of a WebSocket connection is called the consumer.
Each consumer can in turn subscribe to multiple cable channels. Each channel encapsulates
a logical unit of work, similar to what a controller does in a regular MVC setup. For example,
-you could have a `ChatChannel` and a `AppearancesChannel`, and a consumer could be subscribed to either
+you could have a `ChatChannel` and an `AppearancesChannel`, and a consumer could be subscribed to either
or to both of these channels. At the very least, a consumer should be subscribed to one channel.
When the consumer is subscribed to a channel, they act as a subscriber. The connection between
@@ -188,7 +188,7 @@ can be reached as remote procedure calls via a subscription's `perform` method.
The appearance example was all about exposing server functionality to client-side invocation over the WebSocket connection.
But the great thing about WebSockets is that it's a two-way street. So now let's show an example where the server invokes
-action on the client.
+an action on the client.
This is a web notification channel that allows you to trigger client-side web notifications when you broadcast to the right
streams:
@@ -298,22 +298,24 @@ See the [rails/actioncable-examples](http://github.com/rails/actioncable-example
## Configuration
-Action Cable has three required configurations: the Redis connection, allowed request origins, and the cable server url (which can optionally be set on the client side).
+Action Cable has three required configurations: a subscription adapter, allowed request origins, and the cable server URL (which can optionally be set on the client side).
### Redis
By default, `ActionCable::Server::Base` will look for a configuration file in `Rails.root.join('config/cable.yml')`.
-This file must specify a Redis url for each Rails environment. It may use the following format:
+This file must specify an adapter and a URL for each Rails environment. It may use the following format:
```yaml
production: &production
+ adapter: redis
url: redis://10.10.3.153:6381
development: &development
+ adapter: redis
url: redis://localhost:6379
test: *development
```
-You can also change the location of the Redis config file in a Rails initializer with something like:
+You can also change the location of the Action Cable config file in a Rails initializer with something like:
```ruby
Rails.application.paths.add "config/cable", with: "somewhere/else/cable.yml"
@@ -324,7 +326,7 @@ Rails.application.paths.add "config/cable", with: "somewhere/else/cable.yml"
Action Cable will only accept requests from specified origins, which are passed to the server config as an array. The origins can be instances of strings or regular expressions, against which a check for match will be performed.
```ruby
-ActionCable.server.config.allowed_request_origins = ['http://rubyonrails.com', /http:\/\/ruby.*/]
+Rails.application.config.action_cable.allowed_request_origins = ['http://rubyonrails.com', /http:\/\/ruby.*/]
```
When running in the development environment, this defaults to "http://localhost:3000".
@@ -332,7 +334,7 @@ When running in the development environment, this defaults to "http://localhost:
To disable and allow requests from any origin:
```ruby
-ActionCable.server.config.disable_request_forgery_protection = true
+Rails.application.config.action_cable.disable_request_forgery_protection = true
```
### Consumer Configuration
@@ -374,7 +376,7 @@ App.cable = ActionCable.createConsumer()
The other common option to configure is the log tags applied to the per-connection logger. Here's close to what we're using in Basecamp:
```ruby
-ActionCable.server.config.log_tags = [
+Rails.application.config.action_cable.log_tags = [
-> request { request.env['bc.account_id'] || "no-account" },
:action_cable,
-> request { request.uuid }
@@ -389,7 +391,7 @@ Also note that your server must provide at least the same number of database con
## Running the cable server
### Standalone
-The cable server(s) is separated from your normal application server. It's still a rack application, but it is its own rack
+The cable server(s) is separated from your normal application server. It's still a Rack application, but it is its own Rack
application. The recommended basic setup is as follows:
```ruby
@@ -431,12 +433,9 @@ The WebSocket server doesn't have access to the session, but it has access to th
## Dependencies
-Action Cable is currently tied to Redis through its use of the pubsub feature to route
-messages back and forth over the WebSocket cable connection. This dependency may well
-be alleviated in the future, but for the moment that's what it is. So be sure to have
-Redis installed and running.
+Action Cable provides a subscription adapter interface to process its pubsub internals. By default, asynchronous, inline, PostgreSQL, evented Redis, and non-evented Redis adapters are included. The default adapter in new Rails applications is the asynchronous (`async`) adapter. To create your own adapter, you can look at `ActionCable::SubscriptionAdapter::Base` for all methods that must be implemented, and any of the adapters included within ActionCable as example implementations.
-The Ruby side of things is built on top of [faye-websocket](https://github.com/faye/faye-websocket-ruby) and [concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby).
+The Ruby side of things is built on top of [websocket-driver](https://github.com/faye/websocket-driver-ruby), [nio4r](https://github.com/celluloid/nio4r), and [concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby).
## Deployment
diff --git a/actioncable/lib/action_cable/connection/base.rb b/actioncable/lib/action_cable/connection/base.rb
index b5f898436a..1acef93025 100644
--- a/actioncable/lib/action_cable/connection/base.rb
+++ b/actioncable/lib/action_cable/connection/base.rb
@@ -35,7 +35,7 @@ module ActionCable
#
# First, we declare that this connection can be identified by its current_user. This allows us later to be able to find all connections
# established for that current_user (and potentially disconnect them if the user was removed from an account). You can declare as many
- # identification indexes as you like. Declaring an identification means that a attr_accessor is automatically set for that key.
+ # identification indexes as you like. Declaring an identification means that an attr_accessor is automatically set for that key.
#
# Second, we rely on the fact that the WebSocket connection is established with the cookies from the domain being sent along. This makes
# it easy to use signed cookies that were set when logging in via a web interface to authorize the WebSocket connection.
@@ -185,12 +185,14 @@ module ActionCable
end
def respond_to_successful_request
+ logger.info successful_request_message
websocket.rack_response
end
def respond_to_invalid_request
close if websocket.alive?
+ logger.error invalid_request_message
logger.info finished_request_message
[ 404, { 'Content-Type' => 'text/plain' }, [ 'Page not found' ] ]
end
@@ -205,7 +207,7 @@ module ActionCable
'Started %s "%s"%s for %s at %s' % [
request.request_method,
request.filtered_path,
- websocket.possible? ? ' [WebSocket]' : '',
+ websocket.possible? ? ' [WebSocket]' : '[non-WebSocket]',
request.ip,
Time.now.to_s ]
end
@@ -213,10 +215,22 @@ module ActionCable
def finished_request_message
'Finished "%s"%s for %s at %s' % [
request.filtered_path,
- websocket.possible? ? ' [WebSocket]' : '',
+ websocket.possible? ? ' [WebSocket]' : '[non-WebSocket]',
request.ip,
Time.now.to_s ]
end
+
+ def invalid_request_message
+ 'Failed to upgrade to WebSocket (REQUEST_METHOD: %s, HTTP_CONNECTION: %s, HTTP_UPGRADE: %s)' % [
+ env["REQUEST_METHOD"], env["HTTP_CONNECTION"], env["HTTP_UPGRADE"]
+ ]
+ end
+
+ def successful_request_message
+ 'Successfully upgraded to WebSocket (REQUEST_METHOD: %s, HTTP_CONNECTION: %s, HTTP_UPGRADE: %s)' % [
+ env["REQUEST_METHOD"], env["HTTP_CONNECTION"], env["HTTP_UPGRADE"]
+ ]
+ end
end
end
end
diff --git a/actioncable/lib/action_cable/server/broadcasting.rb b/actioncable/lib/action_cable/server/broadcasting.rb
index 7e8aef45f4..b87232671b 100644
--- a/actioncable/lib/action_cable/server/broadcasting.rb
+++ b/actioncable/lib/action_cable/server/broadcasting.rb
@@ -23,7 +23,7 @@ module ActionCable
broadcaster_for(broadcasting).broadcast(message)
end
- # Returns a broadcaster for a named <tt>broadcasting</tt> that can be reused. Useful when you have a object that
+ # Returns a broadcaster for a named <tt>broadcasting</tt> that can be reused. Useful when you have an object that
# may need multiple spots to transmit to a specific broadcasting over and over.
def broadcaster_for(broadcasting)
Broadcaster.new(self, broadcasting)