pusher 0.8.3 → 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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}/events"
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
- unless defined?(EventMachine) && EventMachine.reactor_running?
29
- raise Error, "In order to use trigger_async you must be running inside an eventmachine loop"
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
- require 'net/http' unless defined?(Net::HTTP)
76
- require 'net/https' if (ssl? && !defined?(Net::HTTPS))
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 handle_response(status_code, body)
171
- case status_code
172
- when 202
173
- return true
174
- when 400
175
- raise Error, "Bad request: #{body}"
176
- when 401
177
- raise AuthenticationError, body
178
- when 404
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
- raise Error, "Unknown error (status code #{status_code}): #{body}"
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
- def ssl?
186
- @uri.scheme == 'https'
151
+ request = Pusher::Request.new(:post, @uri + 'events', params, body)
187
152
  end
188
153
  end
189
154
  end
@@ -4,32 +4,104 @@ require 'multi_json'
4
4
 
5
5
  module Pusher
6
6
  class Request
7
- attr_reader :body, :query
7
+ def initialize(verb, uri, params, body = nil, token = nil)
8
+ @verb = verb
9
+ @uri = uri
8
10
 
9
- def initialize(resource, event_name, data, socket_id, token = nil)
10
- params = {
11
- :name => event_name,
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
- @body = case data
16
- when String
17
- data
18
- else
19
- begin
20
- MultiJson.encode(data)
21
- rescue MultiJson::DecodeError => e
22
- Pusher.logger.error("Could not convert #{data.inspect} into JSON")
23
- raise e
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
- request = Signature::Request.new('POST', resource.path, params)
29
- auth_hash = request.sign(token || Pusher.authentication_token)
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
- @query = params.merge(auth_hash)
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
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "pusher"
6
- s.version = "0.8.3"
6
+ s.version = "0.8.4"
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.authors = ["Pusher"]
9
9
  s.email = ["support@pusher.com"]
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.3
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-09-20 00:00:00.000000000Z
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: &70297839817840 !ruby/object:Gem::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: *70297839817840
24
+ version_requirements: *70240168472560
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: crack
27
- requirement: &70297839817300 !ruby/object:Gem::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: *70297839817300
35
+ version_requirements: *70240168472100
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: ruby-hmac
38
- requirement: &70297839816760 !ruby/object:Gem::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: *70297839816760
46
+ version_requirements: *70240168471520
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: signature
49
- requirement: &70297839816180 !ruby/object:Gem::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: *70297839816180
57
+ version_requirements: *70240168470820
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rspec
60
- requirement: &70297839815680 !ruby/object:Gem::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: *70297839815680
68
+ version_requirements: *70240168470200
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: webmock
71
- requirement: &70297839815180 !ruby/object:Gem::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: *70297839815180
79
+ version_requirements: *70240168469760
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: em-http-request
82
- requirement: &70297839814460 !ruby/object:Gem::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: *70297839814460
90
+ version_requirements: *70240168468900
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: rake
93
- requirement: &70297839813680 !ruby/object:Gem::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: *70297839813680
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.7
145
+ rubygems_version: 1.8.6
146
146
  signing_key:
147
147
  specification_version: 3
148
148
  summary: Pusher API client