pusher 0.8.3 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/pusher/channel.rb +32 -67
- data/lib/pusher/request.rb +91 -19
- data/pusher.gemspec +1 -1
- data/spec/channel_spec.rb +18 -0
- metadata +19 -19
data/lib/pusher/channel.rb
CHANGED
@@ -9,7 +9,7 @@ module Pusher
|
|
9
9
|
|
10
10
|
def initialize(base_url, name)
|
11
11
|
@uri = base_url.dup
|
12
|
-
@uri.path = @uri.path + "/channels/#{name}/
|
12
|
+
@uri.path = @uri.path + "/channels/#{name}/"
|
13
13
|
@name = name
|
14
14
|
end
|
15
15
|
|
@@ -25,33 +25,8 @@ module Pusher
|
|
25
25
|
# probably want to run your application inside a server such as thin
|
26
26
|
#
|
27
27
|
def trigger_async(event_name, data, socket_id = nil, &block)
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
require 'em-http' unless defined?(EventMachine::HttpRequest)
|
32
|
-
|
33
|
-
request = Pusher::Request.new(@uri, event_name, data, socket_id)
|
34
|
-
|
35
|
-
deferrable = EM::DefaultDeferrable.new
|
36
|
-
|
37
|
-
http = EventMachine::HttpRequest.new(@uri).post({
|
38
|
-
:query => request.query, :timeout => 5, :body => request.body,
|
39
|
-
:head => {'Content-Type'=> 'application/json'}
|
40
|
-
})
|
41
|
-
http.callback {
|
42
|
-
begin
|
43
|
-
handle_response(http.response_header.status, http.response.chomp)
|
44
|
-
deferrable.succeed
|
45
|
-
rescue => e
|
46
|
-
deferrable.fail(e)
|
47
|
-
end
|
48
|
-
}
|
49
|
-
http.errback {
|
50
|
-
Pusher.logger.debug("Network error connecting to pusher: #{http.inspect}")
|
51
|
-
deferrable.fail(Error.new("Network error connecting to pusher"))
|
52
|
-
}
|
53
|
-
|
54
|
-
deferrable
|
28
|
+
request = construct_event_request(event_name, data, socket_id)
|
29
|
+
request.send_async
|
55
30
|
end
|
56
31
|
|
57
32
|
# Trigger event
|
@@ -72,31 +47,8 @@ module Pusher
|
|
72
47
|
# @raise [Pusher::HTTPError] on any error raised inside Net::HTTP - the original error is available in the original_error attribute
|
73
48
|
#
|
74
49
|
def trigger!(event_name, data, socket_id = nil)
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
@http_sync ||= begin
|
79
|
-
http = Net::HTTP.new(@uri.host, @uri.port)
|
80
|
-
http.use_ssl = true if ssl?
|
81
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if ssl?
|
82
|
-
http
|
83
|
-
end
|
84
|
-
|
85
|
-
request = Pusher::Request.new(@uri, event_name, data, socket_id)
|
86
|
-
|
87
|
-
begin
|
88
|
-
response = @http_sync.post("#{@uri.path}?#{request.query.to_params}",
|
89
|
-
request.body, { 'Content-Type'=> 'application/json' })
|
90
|
-
rescue Errno::EINVAL, Errno::ECONNRESET, Errno::ECONNREFUSED,
|
91
|
-
Timeout::Error, EOFError,
|
92
|
-
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
|
93
|
-
Net::ProtocolError => e
|
94
|
-
error = Pusher::HTTPError.new("#{e.message} (#{e.class})")
|
95
|
-
error.original_error = e
|
96
|
-
raise error
|
97
|
-
end
|
98
|
-
|
99
|
-
return handle_response(response.code.to_i, response.body.chomp)
|
50
|
+
request = construct_event_request(event_name, data, socket_id)
|
51
|
+
request.send_sync
|
100
52
|
end
|
101
53
|
|
102
54
|
# Trigger event, catching and logging any errors.
|
@@ -111,6 +63,17 @@ module Pusher
|
|
111
63
|
Pusher.logger.debug(e.backtrace.join("\n"))
|
112
64
|
end
|
113
65
|
|
66
|
+
# Request channel stats
|
67
|
+
#
|
68
|
+
# @return [Hash] See Pusher api docs for reported stats
|
69
|
+
# @raise [Pusher::Error] on invalid Pusher response - see the error message for more details
|
70
|
+
# @raise [Pusher::HTTPError] on any error raised inside Net::HTTP - the original error is available in the original_error attribute
|
71
|
+
#
|
72
|
+
def stats
|
73
|
+
request = Pusher::Request.new(:get, @uri + 'stats', {})
|
74
|
+
return request.send_sync
|
75
|
+
end
|
76
|
+
|
114
77
|
# Compute authentication string required to subscribe to this channel.
|
115
78
|
#
|
116
79
|
# See http://pusher.com/docs/auth_signatures for more details.
|
@@ -167,23 +130,25 @@ module Pusher
|
|
167
130
|
|
168
131
|
private
|
169
132
|
|
170
|
-
def
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
raise Error, "Resource not found: app_id is probably invalid"
|
133
|
+
def construct_event_request(event_name, data, socket_id)
|
134
|
+
params = {
|
135
|
+
:name => event_name,
|
136
|
+
}
|
137
|
+
params[:socket_id] = socket_id if socket_id
|
138
|
+
|
139
|
+
body = case data
|
140
|
+
when String
|
141
|
+
data
|
180
142
|
else
|
181
|
-
|
143
|
+
begin
|
144
|
+
MultiJson.encode(data)
|
145
|
+
rescue MultiJson::DecodeError => e
|
146
|
+
Pusher.logger.error("Could not convert #{data.inspect} into JSON")
|
147
|
+
raise e
|
148
|
+
end
|
182
149
|
end
|
183
|
-
end
|
184
150
|
|
185
|
-
|
186
|
-
@uri.scheme == 'https'
|
151
|
+
request = Pusher::Request.new(:post, @uri + 'events', params, body)
|
187
152
|
end
|
188
153
|
end
|
189
154
|
end
|
data/lib/pusher/request.rb
CHANGED
@@ -4,32 +4,104 @@ require 'multi_json'
|
|
4
4
|
|
5
5
|
module Pusher
|
6
6
|
class Request
|
7
|
-
|
7
|
+
def initialize(verb, uri, params, body = nil, token = nil)
|
8
|
+
@verb = verb
|
9
|
+
@uri = uri
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
:
|
12
|
-
|
13
|
-
params[:socket_id] = socket_id if socket_id
|
11
|
+
if body
|
12
|
+
@body = body
|
13
|
+
params[:body_md5] = Digest::MD5.hexdigest(body)
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
request = Signature::Request.new(verb.to_s.upcase, uri.path, params)
|
17
|
+
auth_hash = request.sign(token || Pusher.authentication_token)
|
18
|
+
@params = params.merge(auth_hash)
|
19
|
+
end
|
20
|
+
|
21
|
+
def send_sync
|
22
|
+
require 'net/http' unless defined?(Net::HTTP)
|
23
|
+
require 'net/https' if (ssl? && !defined?(Net::HTTPS))
|
24
|
+
|
25
|
+
@http_sync ||= begin
|
26
|
+
http = Net::HTTP.new(@uri.host, @uri.port)
|
27
|
+
http.use_ssl = true if ssl?
|
28
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if ssl?
|
29
|
+
http
|
30
|
+
end
|
31
|
+
|
32
|
+
begin
|
33
|
+
case @verb
|
34
|
+
when :post
|
35
|
+
response = @http_sync.post("#{@uri.path}?#{@params.to_params}",
|
36
|
+
@body, { 'Content-Type'=> 'application/json' })
|
37
|
+
when :get
|
38
|
+
response = @http_sync.get("#{@uri.path}?#{@params.to_params}",
|
39
|
+
{ 'Content-Type'=> 'application/json' })
|
40
|
+
else
|
41
|
+
raise "Unknown verb"
|
24
42
|
end
|
43
|
+
rescue Errno::EINVAL, Errno::ECONNRESET, Errno::ECONNREFUSED,
|
44
|
+
Errno::ETIMEDOUT, Errno::EHOSTUNREACH, Errno::ECONNRESET,
|
45
|
+
Timeout::Error, EOFError,
|
46
|
+
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
|
47
|
+
Net::ProtocolError => e
|
48
|
+
error = Pusher::HTTPError.new("#{e.message} (#{e.class})")
|
49
|
+
error.original_error = e
|
50
|
+
raise error
|
25
51
|
end
|
26
|
-
params[:body_md5] = Digest::MD5.hexdigest(body)
|
27
52
|
|
28
|
-
|
29
|
-
|
53
|
+
return handle_response(response.code.to_i, response.body.chomp)
|
54
|
+
end
|
55
|
+
|
56
|
+
def send_async
|
57
|
+
unless defined?(EventMachine) && EventMachine.reactor_running?
|
58
|
+
raise Error, "In order to use trigger_async you must be running inside an eventmachine loop"
|
59
|
+
end
|
60
|
+
require 'em-http' unless defined?(EventMachine::HttpRequest)
|
61
|
+
|
62
|
+
deferrable = EM::DefaultDeferrable.new
|
63
|
+
|
64
|
+
http = EventMachine::HttpRequest.new(@uri).post({
|
65
|
+
:query => @params, :timeout => 5, :body => @body,
|
66
|
+
:head => {'Content-Type'=> 'application/json'}
|
67
|
+
})
|
68
|
+
http.callback {
|
69
|
+
begin
|
70
|
+
handle_response(http.response_header.status, http.response.chomp)
|
71
|
+
deferrable.succeed
|
72
|
+
rescue => e
|
73
|
+
deferrable.fail(e)
|
74
|
+
end
|
75
|
+
}
|
76
|
+
http.errback {
|
77
|
+
Pusher.logger.debug("Network error connecting to pusher: #{http.inspect}")
|
78
|
+
deferrable.fail(Error.new("Network error connecting to pusher"))
|
79
|
+
}
|
30
80
|
|
31
|
-
|
81
|
+
deferrable
|
32
82
|
end
|
33
83
|
|
84
|
+
private
|
85
|
+
|
86
|
+
def handle_response(status_code, body)
|
87
|
+
case status_code
|
88
|
+
when 200
|
89
|
+
return MultiJson.decode(body, :symbolize_keys => true)
|
90
|
+
when 202
|
91
|
+
return true
|
92
|
+
when 400
|
93
|
+
raise Error, "Bad request: #{body}"
|
94
|
+
when 401
|
95
|
+
raise AuthenticationError, body
|
96
|
+
when 404
|
97
|
+
raise Error, "Resource not found: app_id is probably invalid"
|
98
|
+
else
|
99
|
+
raise Error, "Unknown error (status code #{status_code}): #{body}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def ssl?
|
104
|
+
@uri.scheme == 'https'
|
105
|
+
end
|
34
106
|
end
|
35
107
|
end
|
data/pusher.gemspec
CHANGED
data/spec/channel_spec.rb
CHANGED
@@ -187,6 +187,24 @@ describe Pusher::Channel do
|
|
187
187
|
end
|
188
188
|
end
|
189
189
|
|
190
|
+
describe "stats" do
|
191
|
+
before :each do
|
192
|
+
@api_path = %r{/apps/20/channels/presence-test_channel/stats}
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should call the user_count api" do
|
196
|
+
WebMock.stub_request(:get, @api_path).to_return({
|
197
|
+
:status => 200,
|
198
|
+
:body => JSON.generate(:user_count => 1)
|
199
|
+
})
|
200
|
+
@channel = Pusher['presence-test_channel']
|
201
|
+
|
202
|
+
@channel.stats.should == {
|
203
|
+
:user_count => 1
|
204
|
+
}
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
190
208
|
describe "socket_auth" do
|
191
209
|
before :each do
|
192
210
|
@channel = Pusher['test_channel']
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pusher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-10-14 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|
16
|
-
requirement: &
|
16
|
+
requirement: &70240168472560 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '1.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70240168472560
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: crack
|
27
|
-
requirement: &
|
27
|
+
requirement: &70240168472100 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 0.1.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70240168472100
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: ruby-hmac
|
38
|
-
requirement: &
|
38
|
+
requirement: &70240168471520 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 0.4.0
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70240168471520
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: signature
|
49
|
-
requirement: &
|
49
|
+
requirement: &70240168470820 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 0.1.2
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70240168470820
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: rspec
|
60
|
-
requirement: &
|
60
|
+
requirement: &70240168470200 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '2.0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70240168470200
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: webmock
|
71
|
-
requirement: &
|
71
|
+
requirement: &70240168469760 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70240168469760
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: em-http-request
|
82
|
-
requirement: &
|
82
|
+
requirement: &70240168468900 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ~>
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: 1.0.0
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70240168468900
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: rake
|
93
|
-
requirement: &
|
93
|
+
requirement: &70240168467600 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,7 +98,7 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70240168467600
|
102
102
|
description: Wrapper for pusher.com REST api
|
103
103
|
email:
|
104
104
|
- support@pusher.com
|
@@ -142,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
142
|
version: '0'
|
143
143
|
requirements: []
|
144
144
|
rubyforge_project:
|
145
|
-
rubygems_version: 1.8.
|
145
|
+
rubygems_version: 1.8.6
|
146
146
|
signing_key:
|
147
147
|
specification_version: 3
|
148
148
|
summary: Pusher API client
|