pusher 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/README.md +109 -38
- data/lib/pusher.rb +9 -21
- data/lib/pusher/channel.rb +17 -29
- data/lib/pusher/client.rb +186 -30
- data/lib/pusher/query_encoder.rb +47 -0
- data/lib/pusher/request.rb +30 -85
- data/lib/pusher/resource.rb +36 -0
- data/pusher.gemspec +1 -1
- data/spec/channel_spec.rb +12 -143
- data/spec/client_spec.rb +208 -14
- data/spec/spec_helper.rb +8 -1
- data/spec/web_hook_spec.rb +7 -5
- metadata +112 -114
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -3,80 +3,151 @@ Pusher gem
|
|
3
3
|
|
4
4
|
[![Build Status](https://secure.travis-ci.org/pusher/pusher-gem.png?branch=master)](http://travis-ci.org/pusher/pusher-gem)
|
5
5
|
|
6
|
-
|
7
|
-
---------------
|
6
|
+
## Configuration
|
8
7
|
|
9
|
-
After registering at <http://pusher.com> configure your app with the security credentials
|
8
|
+
After registering at <http://pusher.com> configure your app with the security credentials.
|
9
|
+
|
10
|
+
### Global
|
11
|
+
|
12
|
+
The most standard way of configuring Pusher is to do it globally on the Pusher class.
|
10
13
|
|
11
14
|
Pusher.app_id = 'your-pusher-app-id'
|
12
15
|
Pusher.key = 'your-pusher-key'
|
13
16
|
Pusher.secret = 'your-pusher-secret'
|
14
17
|
|
15
|
-
|
18
|
+
Global configuration will automatically be set from the `PUSHER_URL` environment variable if it exists. This should be in the form `http://KEY:SECRET@api.pusherapp.com/apps/APP_ID`. On Heroku this environment variable will already be set.
|
19
|
+
|
20
|
+
If you need to make requests via a HTTP proxy then it can be configured
|
21
|
+
|
22
|
+
Pusher.http_proxy = 'http://(user):(password)@(host):(port)'
|
23
|
+
|
24
|
+
By default API requests are made over HTTP. HTTPS can be used by setting
|
25
|
+
|
26
|
+
Pusher.encrypted = true
|
27
|
+
|
28
|
+
### Instantiating a Pusher client
|
29
|
+
|
30
|
+
Sometimes you may have multiple sets of API keys, or want different configuration in different parts of your application. In these scenarios, a pusher `client` may be configured:
|
31
|
+
|
32
|
+
pusher_client = Pusher.new({
|
33
|
+
app_id: 'your-pusher-app-id',
|
34
|
+
key: 'your-pusher-key',
|
35
|
+
secret: 'your-pusher-secret'
|
36
|
+
})
|
37
|
+
|
38
|
+
This `client` will have all the functionality listed on the main Pusher class (which proxies to a client internally).
|
16
39
|
|
17
|
-
Pusher['a_channel'].trigger!('an_event', {:some => 'data'})
|
18
40
|
|
19
|
-
|
41
|
+
|
42
|
+
## Interacting with the Pusher service
|
43
|
+
|
44
|
+
The Pusher gem contains a number of helpers for interacting with the service. As a general rule, the library adheres to a set of conventions that we have aimed to make universal.
|
45
|
+
|
46
|
+
### Handling errors
|
47
|
+
|
48
|
+
Handle errors by rescuing `Pusher::Error` (all errors are descendants of this error)
|
20
49
|
|
21
50
|
begin
|
22
|
-
Pusher
|
51
|
+
Pusher.trigger('a_channel', 'an_event', {:some => 'data'})
|
23
52
|
rescue Pusher::Error => e
|
24
53
|
# (Pusher::AuthenticationError, Pusher::HTTPError, or Pusher::Error)
|
25
54
|
end
|
26
55
|
|
27
|
-
|
56
|
+
### Logging
|
28
57
|
|
29
|
-
|
58
|
+
Errors are logged to `Pusher.logger`. It will by default log at info level to STDOUT using `Logger` from the standard library, however you can assign any logger:
|
30
59
|
|
31
|
-
|
60
|
+
Pusher.logger = Rails.logger
|
61
|
+
|
62
|
+
### Publishing events
|
63
|
+
|
64
|
+
An event can be sent to Pusher in in the following ways:
|
65
|
+
|
66
|
+
# on the Pusher class
|
67
|
+
Pusher.trigger('channel_name', 'event_name', {some: 'data'})
|
68
|
+
Pusher.trigger(['channel_1', 'channel_2'], 'event_name', {some: 'data'})
|
69
|
+
|
70
|
+
# or on a pusher_client
|
71
|
+
pusher_client.trigger(['your_channels'], 'your_event_name', {some: 'data'})
|
72
|
+
|
73
|
+
Note: the first `channels` argument can contain multiple channels you'd like your event and data payload to go to. There is a limit of 100 on the number of channels this can contain.
|
74
|
+
|
75
|
+
An optional fourth argument of this method can specify a `socket_id` that will be excluded from receiving the event (generally the user where the event originated -- see <http://pusher.com/docs/publisher_api_guide/publisher_excluding_recipients> for more info).
|
76
|
+
|
77
|
+
#### Original publisher API
|
78
|
+
|
79
|
+
Most examples and documentation will refer to the following syntax for triggering an event:
|
32
80
|
|
33
81
|
Pusher['a_channel'].trigger('an_event', {:some => 'data'})
|
34
82
|
|
35
|
-
|
36
|
-
-------
|
83
|
+
This will continue to work, but will be replaced as the canonical version by `Pusher.trigger` which supports multiple channels.
|
37
84
|
|
38
|
-
|
85
|
+
### Generic requests to the Pusher REST API
|
39
86
|
|
40
|
-
|
87
|
+
Aside from triggering events, the REST API also supports a number of operations for querying the state of the system. A reference of the available methods is available at <http://pusher.com/docs/rest_api>.
|
88
|
+
|
89
|
+
All requests must be signed by using your secret key, which is handled automatically using these methods:
|
90
|
+
|
91
|
+
# using the Pusher class
|
92
|
+
Pusher.get('url_without_app_id', params)
|
93
|
+
|
94
|
+
# using a client
|
95
|
+
pusher_client.post('url_without_app_id', params)
|
96
|
+
|
97
|
+
Note that you don't need to specify your app_id in the URL, as this is inferred from your credentials. As with the trigger method above, `_async` can be suffixed to the method name to return a deferrable.
|
41
98
|
|
42
|
-
Asynchronous
|
43
|
-
-----------------------
|
99
|
+
### Asynchronous requests
|
44
100
|
|
45
|
-
|
101
|
+
If you are running your application in an evented environment, you may want to use the asynchronous versions of the Pusher API methods to avoid blocking. The convention for this is to add the suffix `_async` to the method, e.g. `trigger_async` or `post_async`.
|
46
102
|
|
47
103
|
You need to be running eventmachine to make use of this functionality. This is already the case if, for example, you're deploying to Heroku or using the Thin web server. You will also need to add `em-http-request` to your Gemfile.
|
48
104
|
|
49
|
-
|
105
|
+
When using an asynchronous version of a method, it will return a deferrable.
|
50
106
|
|
51
|
-
|
107
|
+
Pusher.trigger_async(['a_channel'], 'an_event', {
|
52
108
|
:some => 'data'
|
53
|
-
}, socket_id)
|
54
|
-
deferrable.callback {
|
109
|
+
}, socket_id).callback {
|
55
110
|
# Do something on success
|
56
|
-
}
|
57
|
-
deferrable.errback { |error|
|
111
|
+
}.errback { |error|
|
58
112
|
# error is a instance of Pusher::Error
|
59
113
|
}
|
60
114
|
|
61
|
-
Private channels
|
62
|
-
----------------
|
63
115
|
|
64
|
-
The Pusher Gem also deals with signing requests for authenticated private channels. A quick Rails controller example:
|
65
116
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
117
|
+
## Authenticating subscription requests
|
118
|
+
|
119
|
+
It's possible to use the gem to authenticate subscription requests to private or presence channels. The `authenticate` method is available on a channel object for this purpose and returns a JSON object that can be returned to the client that made the request. More information on this authentication scheme can be found in the docs on <http://pusher.com>
|
120
|
+
|
121
|
+
### Private channels
|
122
|
+
|
123
|
+
Pusher['private-my_channel'].authenticate(params[:socket_id])
|
70
124
|
|
71
|
-
|
72
|
-
--------
|
125
|
+
### Presence channels
|
73
126
|
|
74
|
-
|
127
|
+
These work in a very similar way, but require a unique identifier for the user being authenticated, and optionally some attributes that are provided to clients via presence events:
|
75
128
|
|
76
|
-
|
77
|
-
|
129
|
+
Pusher['presence-my_channel'].authenticate(params[:socket_id], {
|
130
|
+
user_id: 'user_id',
|
131
|
+
user_info: {} # optional
|
132
|
+
})
|
78
133
|
|
79
|
-
Use bundler in order to run specs with the correct dependencies.
|
80
134
|
|
81
|
-
|
82
|
-
|
135
|
+
|
136
|
+
## Receiving WebHooks
|
137
|
+
|
138
|
+
A WebHook object may be created to validate received WebHooks against your app credentials, and to extract events. It should be created with the `Rack::Request` object (available as `request` in Rails controllers or Sinatra handlers for example).
|
139
|
+
|
140
|
+
webhook = Pusher.webhook(request)
|
141
|
+
if webhook.valid?
|
142
|
+
webhook.events.each do |event|
|
143
|
+
case event["name"]
|
144
|
+
when 'channel_occupied'
|
145
|
+
puts "Channel occupied: #{event["channel"]}"
|
146
|
+
when 'channel_vacated'
|
147
|
+
puts "Channel vacated: #{event["channel"]}"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
render text: 'ok'
|
151
|
+
else
|
152
|
+
render text: 'invalid', status: 401
|
153
|
+
end
|
data/lib/pusher.rb
CHANGED
@@ -7,12 +7,11 @@ require 'pusher/client'
|
|
7
7
|
# Used for configuring API credentials and creating Channel objects
|
8
8
|
#
|
9
9
|
module Pusher
|
10
|
-
# All
|
11
|
-
# errors
|
10
|
+
# All errors descend from this class so they can be easily rescued
|
12
11
|
#
|
13
12
|
# @example
|
14
13
|
# begin
|
15
|
-
# Pusher
|
14
|
+
# Pusher.trigger('channel_name', 'event_name, {:some => 'data'})
|
16
15
|
# rescue Pusher::Error => e
|
17
16
|
# # Do something on error
|
18
17
|
# end
|
@@ -24,31 +23,18 @@ module Pusher
|
|
24
23
|
class << self
|
25
24
|
extend Forwardable
|
26
25
|
|
27
|
-
def_delegators :default_client, :scheme, :host, :port, :app_id, :key, :secret
|
28
|
-
def_delegators :default_client, :scheme=, :host=, :port=, :app_id=, :key=, :secret=
|
26
|
+
def_delegators :default_client, :scheme, :host, :port, :app_id, :key, :secret, :http_proxy
|
27
|
+
def_delegators :default_client, :scheme=, :host=, :port=, :app_id=, :key=, :secret=, :http_proxy=
|
29
28
|
|
30
29
|
def_delegators :default_client, :authentication_token, :url
|
31
30
|
def_delegators :default_client, :encrypted=, :url=
|
32
31
|
|
33
|
-
def_delegators :default_client, :
|
32
|
+
def_delegators :default_client, :get, :get_async, :post, :post_async
|
33
|
+
def_delegators :default_client, :channels, :channel_info, :trigger, :trigger_async
|
34
|
+
def_delegators :default_client, :webhook, :channel, :[]
|
34
35
|
|
35
36
|
attr_writer :logger
|
36
37
|
|
37
|
-
# Return a channel by name
|
38
|
-
#
|
39
|
-
# @example
|
40
|
-
# Pusher['my-channel']
|
41
|
-
# @return [Channel]
|
42
|
-
# @raise [ConfigurationError] unless key, secret and app_id have been
|
43
|
-
# configured
|
44
|
-
def [](channel_name)
|
45
|
-
begin
|
46
|
-
default_client[channel_name]
|
47
|
-
rescue ConfigurationError
|
48
|
-
raise ConfigurationError, 'Missing configuration: please check that Pusher.key, Pusher.secret and Pusher.app_id are configured.'
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
38
|
def logger
|
53
39
|
@logger ||= begin
|
54
40
|
log = Logger.new($stdout)
|
@@ -70,5 +56,7 @@ module Pusher
|
|
70
56
|
end
|
71
57
|
|
72
58
|
require 'pusher/channel'
|
59
|
+
require 'pusher/query_encoder'
|
73
60
|
require 'pusher/request'
|
61
|
+
require 'pusher/resource'
|
74
62
|
require 'pusher/webhook'
|
data/lib/pusher/channel.rb
CHANGED
@@ -15,6 +15,9 @@ module Pusher
|
|
15
15
|
|
16
16
|
# Trigger event asynchronously using EventMachine::HttpRequest
|
17
17
|
#
|
18
|
+
# [Deprecated] This method will be removed in a future gem version. Please
|
19
|
+
# switch to Pusher.trigger_async or Pusher::Client#trigger_async instead
|
20
|
+
#
|
18
21
|
# @param (see #trigger!)
|
19
22
|
# @return [EM::DefaultDeferrable]
|
20
23
|
# Attach a callback to be notified of success (with no parameters).
|
@@ -24,13 +27,17 @@ module Pusher
|
|
24
27
|
# @raise [Pusher::Error] unless the eventmachine reactor is running. You
|
25
28
|
# probably want to run your application inside a server such as thin
|
26
29
|
#
|
27
|
-
def trigger_async(event_name, data, socket_id = nil
|
28
|
-
|
29
|
-
|
30
|
+
def trigger_async(event_name, data, socket_id = nil)
|
31
|
+
params = {}
|
32
|
+
params[:socket_id] = socket_id if socket_id
|
33
|
+
@client.trigger_async(name, event_name, data, params)
|
30
34
|
end
|
31
35
|
|
32
36
|
# Trigger event
|
33
37
|
#
|
38
|
+
# [Deprecated] This method will be removed in a future gem version. Please
|
39
|
+
# switch to Pusher.trigger or Pusher::Client#trigger instead
|
40
|
+
#
|
34
41
|
# @example
|
35
42
|
# begin
|
36
43
|
# Pusher['my-channel'].trigger!('an_event', {:some => 'data'})
|
@@ -47,12 +54,16 @@ module Pusher
|
|
47
54
|
# @raise [Pusher::HTTPError] on any error raised inside Net::HTTP - the original error is available in the original_error attribute
|
48
55
|
#
|
49
56
|
def trigger!(event_name, data, socket_id = nil)
|
50
|
-
|
51
|
-
|
57
|
+
params = {}
|
58
|
+
params[:socket_id] = socket_id if socket_id
|
59
|
+
@client.trigger(name, event_name, data, params)
|
52
60
|
end
|
53
61
|
|
54
62
|
# Trigger event, catching and logging any errors.
|
55
63
|
#
|
64
|
+
# [Deprecated] This method will be removed in a future gem version. Please
|
65
|
+
# switch to Pusher.trigger or Pusher::Client#trigger instead
|
66
|
+
#
|
56
67
|
# @note CAUTION! No exceptions will be raised on failure
|
57
68
|
# @param (see #trigger!)
|
58
69
|
#
|
@@ -71,7 +82,7 @@ module Pusher
|
|
71
82
|
# @raise [Pusher::HTTPError] on any error raised inside Net::HTTP - the original error is available in the original_error attribute
|
72
83
|
#
|
73
84
|
def info(attributes = [])
|
74
|
-
@client.
|
85
|
+
@client.get("/channels/#{name}", :info => attributes.join(','))
|
75
86
|
end
|
76
87
|
|
77
88
|
# Compute authentication string required as part of the authentication
|
@@ -132,28 +143,5 @@ module Pusher
|
|
132
143
|
r[:channel_data] = custom_data if custom_data
|
133
144
|
r
|
134
145
|
end
|
135
|
-
|
136
|
-
private
|
137
|
-
|
138
|
-
def construct_event_request(event_name, data, socket_id)
|
139
|
-
params = {
|
140
|
-
:name => event_name,
|
141
|
-
}
|
142
|
-
params[:socket_id] = socket_id if socket_id
|
143
|
-
|
144
|
-
body = case data
|
145
|
-
when String
|
146
|
-
data
|
147
|
-
else
|
148
|
-
begin
|
149
|
-
MultiJson.encode(data)
|
150
|
-
rescue MultiJson::DecodeError => e
|
151
|
-
Pusher.logger.error("Could not convert #{data.inspect} into JSON")
|
152
|
-
raise e
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
request = Pusher::Request.new(:post, @uri + 'events', params, body, nil, @client)
|
157
|
-
end
|
158
146
|
end
|
159
147
|
end
|
data/lib/pusher/client.rb
CHANGED
@@ -2,9 +2,11 @@ require 'signature'
|
|
2
2
|
|
3
3
|
module Pusher
|
4
4
|
class Client
|
5
|
-
attr_accessor :scheme, :host, :port, :app_id, :key, :secret
|
5
|
+
attr_accessor :scheme, :host, :port, :app_id, :key, :secret, :http_proxy
|
6
|
+
attr_reader :proxy
|
7
|
+
|
8
|
+
## CONFIGURATION ##
|
6
9
|
|
7
|
-
# Initializes the client object.
|
8
10
|
def initialize(options = {})
|
9
11
|
options = {
|
10
12
|
:scheme => 'http',
|
@@ -14,6 +16,7 @@ module Pusher
|
|
14
16
|
@scheme, @host, @port, @app_id, @key, @secret = options.values_at(
|
15
17
|
:scheme, :host, :port, :app_id, :key, :secret
|
16
18
|
)
|
19
|
+
self.http_proxy = options[:http_proxy] if options[:http_proxy]
|
17
20
|
end
|
18
21
|
|
19
22
|
# @private Returns the authentication token for the client
|
@@ -47,6 +50,19 @@ module Pusher
|
|
47
50
|
@port = uri.port
|
48
51
|
end
|
49
52
|
|
53
|
+
def http_proxy=(http_proxy)
|
54
|
+
@http_proxy = http_proxy
|
55
|
+
uri = URI.parse(http_proxy)
|
56
|
+
@proxy = {
|
57
|
+
:scheme => uri.scheme,
|
58
|
+
:host => uri.host,
|
59
|
+
:port => uri.port,
|
60
|
+
:user => uri.user,
|
61
|
+
:password => uri.password
|
62
|
+
}
|
63
|
+
@http_proxy
|
64
|
+
end
|
65
|
+
|
50
66
|
# Configure whether Pusher API calls should be made over SSL
|
51
67
|
# (default false)
|
52
68
|
#
|
@@ -59,6 +75,83 @@ module Pusher
|
|
59
75
|
@port = boolean ? 443 : 80
|
60
76
|
end
|
61
77
|
|
78
|
+
def encrypted?
|
79
|
+
@scheme == 'https'
|
80
|
+
end
|
81
|
+
|
82
|
+
## INTERACE WITH THE API ##
|
83
|
+
|
84
|
+
def resource(path)
|
85
|
+
Resource.new(self, path)
|
86
|
+
end
|
87
|
+
|
88
|
+
# GET arbitrary REST API resource using a synchronous http client.
|
89
|
+
# All request signing is handled automatically.
|
90
|
+
#
|
91
|
+
# @example
|
92
|
+
# begin
|
93
|
+
# Pusher.get('/channels', filter_by_prefix: 'private-')
|
94
|
+
# rescue Pusher::Error => e
|
95
|
+
# # Handle error
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# @param path [String] Path excluding /apps/APP_ID
|
99
|
+
# @param params [Hash] API params (see http://pusher.com/docs/rest_api)
|
100
|
+
#
|
101
|
+
# @return [Hash] See Pusher API docs
|
102
|
+
#
|
103
|
+
# @raise [Pusher::Error] Unsuccessful response - see the error message
|
104
|
+
# @raise [Pusher::HTTPError] Error raised inside Net::HTTP. The original error is wrapped in error.original_error
|
105
|
+
#
|
106
|
+
def get(path, params = {})
|
107
|
+
Resource.new(self, path).get(params)
|
108
|
+
end
|
109
|
+
|
110
|
+
# GET arbitrary REST API resource using an asynchronous http client.
|
111
|
+
# All request signing is handled automatically.
|
112
|
+
#
|
113
|
+
# @example
|
114
|
+
# Pusher.get_async('/channels', {
|
115
|
+
# filter_by_prefix: 'private-'
|
116
|
+
# }).callback { |response_hash|
|
117
|
+
# # ...
|
118
|
+
# }.errback { |error|
|
119
|
+
# # error is a instance of Pusher::Error
|
120
|
+
# }
|
121
|
+
#
|
122
|
+
# @param path [String] Path excluding /apps/APP_ID
|
123
|
+
# @param params [Hash] API params (see http://pusher.com/docs/rest_api)
|
124
|
+
#
|
125
|
+
# @return [EM::DefaultDeferrable]
|
126
|
+
#
|
127
|
+
def get_async(path, params = {})
|
128
|
+
Resource.new(self, path).get_async(params)
|
129
|
+
end
|
130
|
+
|
131
|
+
# POST arbitrary REST API resource using a synchronous http client.
|
132
|
+
# Works identially to get method, but posts params as JSON in post body.
|
133
|
+
def post(path, params = {})
|
134
|
+
Resource.new(self, path).post(params)
|
135
|
+
end
|
136
|
+
|
137
|
+
# POST arbitrary REST API resource using an asynchronous http client.
|
138
|
+
# Works identially to get_async method, but posts params as JSON in post
|
139
|
+
# body.
|
140
|
+
def post_async(path, params = {})
|
141
|
+
Resource.new(self, path).post_async(params)
|
142
|
+
end
|
143
|
+
|
144
|
+
## HELPER METHODS ##
|
145
|
+
|
146
|
+
# Convenience method for creating a new WebHook instance for validating
|
147
|
+
# and extracting info from a received WebHook
|
148
|
+
#
|
149
|
+
# @param request [Rack::Request] Either a Rack::Request or a Hash containing :key, :signature, :body, and optionally :content_type.
|
150
|
+
#
|
151
|
+
def webhook(request)
|
152
|
+
WebHook.new(request, self)
|
153
|
+
end
|
154
|
+
|
62
155
|
# Return a convenience channel object by name. No API request is made.
|
63
156
|
#
|
64
157
|
# @example
|
@@ -66,25 +159,26 @@ module Pusher
|
|
66
159
|
# @return [Channel]
|
67
160
|
# @raise [ConfigurationError] unless key, secret and app_id have been
|
68
161
|
# configured
|
69
|
-
def
|
162
|
+
def channel(channel_name)
|
70
163
|
raise ConfigurationError, 'Missing client configuration: please check that key, secret and app_id are configured.' unless configured?
|
71
|
-
|
72
|
-
@channels[channel_name.to_s] ||= Channel.new(url, channel_name, self)
|
164
|
+
Channel.new(url, channel_name, self)
|
73
165
|
end
|
74
166
|
|
167
|
+
alias :[] :channel
|
168
|
+
|
75
169
|
# Request a list of occupied channels from the API
|
76
170
|
#
|
77
171
|
# GET /apps/[id]/channels
|
78
172
|
#
|
79
|
-
# @param
|
173
|
+
# @param params [Hash] Hash of parameters for the API - see REST API docs
|
174
|
+
#
|
80
175
|
# @return [Hash] See Pusher API docs
|
81
|
-
# @raise [Pusher::Error] on invalid Pusher response - see the error message for more details
|
82
|
-
# @raise [Pusher::HTTPError] on any error raised inside Net::HTTP - the original error is available in the original_error attribute
|
83
176
|
#
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
177
|
+
# @raise [Pusher::Error] Unsuccessful response - see the error message
|
178
|
+
# @raise [Pusher::HTTPError] Error raised inside Net::HTTP. The original error is wrapped in error.original_error
|
179
|
+
#
|
180
|
+
def channels(params = {})
|
181
|
+
get('/channels', params)
|
88
182
|
end
|
89
183
|
|
90
184
|
# Request info for a specific channel
|
@@ -92,31 +186,98 @@ module Pusher
|
|
92
186
|
# GET /apps/[id]/channels/[channel_name]
|
93
187
|
#
|
94
188
|
# @param channel_name [String] Channel name
|
95
|
-
# @param
|
189
|
+
# @param params [Hash] Hash of parameters for the API - see REST API docs
|
190
|
+
#
|
96
191
|
# @return [Hash] See Pusher API docs
|
97
|
-
# @raise [Pusher::Error] on invalid Pusher response - see the error message for more details
|
98
|
-
# @raise [Pusher::HTTPError] on any error raised inside Net::HTTP - the original error is available in the original_error attribute
|
99
192
|
#
|
100
|
-
|
101
|
-
|
102
|
-
|
193
|
+
# @raise [Pusher::Error] Unsuccessful response - see the error message
|
194
|
+
# @raise [Pusher::HTTPError] Error raised inside Net::HTTP. The original error is wrapped in error.original_error
|
195
|
+
#
|
196
|
+
def channel_info(channel_name, params = {})
|
197
|
+
get("/channels/#{channel_name}", params)
|
103
198
|
end
|
104
199
|
|
105
200
|
# Trigger an event on one or more channels
|
106
201
|
#
|
107
202
|
# POST /apps/[app_id]/events
|
108
203
|
#
|
109
|
-
# @param channels [Array] One of more channel names
|
204
|
+
# @param channels [String or Array] One of more channel names
|
110
205
|
# @param event_name [String]
|
111
206
|
# @param data [Object] Event data to be triggered in javascript.
|
112
207
|
# Objects other than strings will be converted to JSON
|
113
|
-
# @param
|
208
|
+
# @param params [Hash] Additional parameters to send to api, e.g socket_id
|
209
|
+
#
|
114
210
|
# @return [Hash] See Pusher API docs
|
115
|
-
# @raise [Pusher::Error] on invalid Pusher response - see the error message for more details
|
116
|
-
# @raise [Pusher::HTTPError] on any error raised inside Net::HTTP - the original error is available in the original_error attribute
|
117
211
|
#
|
118
|
-
|
119
|
-
|
212
|
+
# @raise [Pusher::Error] Unsuccessful response - see the error message
|
213
|
+
# @raise [Pusher::HTTPError] Error raised inside Net::HTTP. The original error is wrapped in error.original_error
|
214
|
+
#
|
215
|
+
def trigger(channels, event_name, data, params = {})
|
216
|
+
post('/events', trigger_params(channels, event_name, data, params))
|
217
|
+
end
|
218
|
+
|
219
|
+
# Trigger an event on one or more channels asynchronously.
|
220
|
+
# For parameters see #trigger
|
221
|
+
#
|
222
|
+
def trigger_async(channels, event_name, data, params = {})
|
223
|
+
post_async('/events', trigger_params(channels, event_name, data, params))
|
224
|
+
end
|
225
|
+
|
226
|
+
# @private Construct a net/http http client
|
227
|
+
def net_http_client
|
228
|
+
@_http_sync ||= begin
|
229
|
+
if encrypted?
|
230
|
+
require 'net/https' unless defined?(Net::HTTPS)
|
231
|
+
else
|
232
|
+
require 'net/http' unless defined?(Net::HTTP)
|
233
|
+
end
|
234
|
+
|
235
|
+
http_klass = if (p = @proxy)
|
236
|
+
Net::HTTP.Proxy(p[:host], p[:port], p[:user], p[:password])
|
237
|
+
else
|
238
|
+
Net::HTTP
|
239
|
+
end
|
240
|
+
|
241
|
+
http = http_klass.new(@host, @port)
|
242
|
+
|
243
|
+
if encrypted?
|
244
|
+
http.use_ssl = true
|
245
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
246
|
+
end
|
247
|
+
|
248
|
+
http
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# @private Construct an em-http-request http client
|
253
|
+
def em_http_client(uri)
|
254
|
+
begin
|
255
|
+
unless defined?(EventMachine) && EventMachine.reactor_running?
|
256
|
+
raise Error, "In order to use async calling you must be running inside an eventmachine loop"
|
257
|
+
end
|
258
|
+
require 'em-http' unless defined?(EventMachine::HttpRequest)
|
259
|
+
|
260
|
+
connection_opts = {}
|
261
|
+
|
262
|
+
if @proxy
|
263
|
+
proxy_opts = {
|
264
|
+
:host => @proxy[:host],
|
265
|
+
:port => @proxy[:port]
|
266
|
+
}
|
267
|
+
if @proxy[:user]
|
268
|
+
proxy_opts[:authorization] = [@proxy[:user], @proxy[:password]]
|
269
|
+
end
|
270
|
+
connection_opts[:proxy] = proxy_opts
|
271
|
+
end
|
272
|
+
|
273
|
+
EventMachine::HttpRequest.new(uri, connection_opts)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
private
|
278
|
+
|
279
|
+
def trigger_params(channels, event_name, data, params)
|
280
|
+
channels = [channels] if channels.kind_of?(String)
|
120
281
|
|
121
282
|
encoded_data = case data
|
122
283
|
when String
|
@@ -130,18 +291,13 @@ module Pusher
|
|
130
291
|
end
|
131
292
|
end
|
132
293
|
|
133
|
-
|
294
|
+
return params.merge({
|
134
295
|
:name => event_name,
|
135
296
|
:channels => channels,
|
136
297
|
:data => encoded_data,
|
137
298
|
})
|
138
|
-
|
139
|
-
request = Request.new(:post, @_trigger_url, {}, MultiJson.encode(options), nil, self)
|
140
|
-
return request.send_sync
|
141
299
|
end
|
142
300
|
|
143
|
-
private
|
144
|
-
|
145
301
|
def configured?
|
146
302
|
host && scheme && key && secret && app_id
|
147
303
|
end
|