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.
@@ -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