scout 5.3.5 → 5.4.4.alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/CHANGELOG +0 -12
- data/Gemfile +4 -0
- data/README +8 -0
- data/Rakefile +6 -108
- data/bin/scout +1 -0
- data/lib/scout.rb +5 -4
- data/lib/scout/command.rb +11 -12
- data/lib/scout/command/install.rb +1 -1
- data/lib/scout/command/run.rb +13 -1
- data/lib/scout/command/sign.rb +2 -8
- data/lib/scout/command/stream.rb +50 -0
- data/lib/scout/command/test.rb +1 -1
- data/lib/scout/daemon_spawn.rb +215 -0
- data/lib/scout/plugin.rb +20 -1
- data/lib/scout/server.rb +16 -111
- data/lib/scout/server_base.rb +100 -0
- data/lib/scout/streamer.rb +162 -0
- data/lib/scout/streamer_control.rb +43 -0
- data/lib/scout/version.rb +3 -0
- data/scout.gemspec +27 -0
- data/test/plugins/disk_usage.rb +86 -0
- data/test/scout_test.rb +598 -0
- data/vendor/pusher-gem/Gemfile +2 -0
- data/vendor/pusher-gem/LICENSE +20 -0
- data/vendor/pusher-gem/README.md +80 -0
- data/vendor/pusher-gem/Rakefile +11 -0
- data/vendor/pusher-gem/examples/async_message.rb +28 -0
- data/vendor/pusher-gem/lib/pusher.rb +107 -0
- data/vendor/pusher-gem/lib/pusher/channel.rb +154 -0
- data/vendor/pusher-gem/lib/pusher/request.rb +107 -0
- data/vendor/pusher-gem/pusher.gemspec +28 -0
- data/vendor/pusher-gem/spec/channel_spec.rb +274 -0
- data/vendor/pusher-gem/spec/pusher_spec.rb +87 -0
- data/vendor/pusher-gem/spec/spec_helper.rb +13 -0
- data/vendor/ruby-hmac/History.txt +15 -0
- data/vendor/ruby-hmac/Manifest.txt +11 -0
- data/vendor/ruby-hmac/README.md +41 -0
- data/vendor/ruby-hmac/Rakefile +23 -0
- data/vendor/ruby-hmac/lib/hmac-md5.rb +11 -0
- data/vendor/ruby-hmac/lib/hmac-rmd160.rb +11 -0
- data/vendor/ruby-hmac/lib/hmac-sha1.rb +11 -0
- data/vendor/ruby-hmac/lib/hmac-sha2.rb +25 -0
- data/vendor/ruby-hmac/lib/hmac.rb +118 -0
- data/vendor/ruby-hmac/lib/ruby_hmac.rb +2 -0
- data/vendor/ruby-hmac/ruby-hmac.gemspec +33 -0
- data/vendor/ruby-hmac/test/test_hmac.rb +89 -0
- data/vendor/signature/.document +5 -0
- data/vendor/signature/.gitignore +21 -0
- data/vendor/signature/Gemfile +3 -0
- data/vendor/signature/Gemfile.lock +29 -0
- data/vendor/signature/LICENSE +20 -0
- data/vendor/signature/README.md +55 -0
- data/vendor/signature/Rakefile +2 -0
- data/vendor/signature/VERSION +1 -0
- data/vendor/signature/lib/signature.rb +142 -0
- data/vendor/signature/lib/signature/version.rb +3 -0
- data/vendor/signature/signature.gemspec +22 -0
- data/vendor/signature/spec/signature_spec.rb +176 -0
- data/vendor/signature/spec/spec_helper.rb +10 -0
- data/vendor/util/lib/core_extensions.rb +60 -0
- metadata +120 -84
- data/AUTHORS +0 -4
- data/COPYING +0 -340
- data/INSTALL +0 -18
- data/TODO +0 -6
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 New Bamboo
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,80 @@
|
|
1
|
+
Pusher gem
|
2
|
+
==========
|
3
|
+
|
4
|
+
Getting started
|
5
|
+
---------------
|
6
|
+
|
7
|
+
After registering at <http://pusher.com> configure your app with the security credentials
|
8
|
+
|
9
|
+
Pusher.app_id = 'your-pusher-app-id'
|
10
|
+
Pusher.key = 'your-pusher-key'
|
11
|
+
Pusher.secret = 'your-pusher-secret'
|
12
|
+
|
13
|
+
Trigger an event with {Pusher::Channel#trigger!}
|
14
|
+
|
15
|
+
Pusher['a_channel'].trigger!('an_event', {:some => 'data'})
|
16
|
+
|
17
|
+
Handle errors by rescuing `Pusher::Error` (all Pusher errors are descendants of this error)
|
18
|
+
|
19
|
+
begin
|
20
|
+
Pusher['a_channel'].trigger!('an_event', {:some => 'data'})
|
21
|
+
rescue Pusher::Error => e
|
22
|
+
# (Pusher::AuthenticationError, Pusher::HTTPError, or Pusher::Error)
|
23
|
+
end
|
24
|
+
|
25
|
+
Optionally a socket id may be provided. This will exclude the event from being triggered on this socket id (see <http://pusher.com/docs/publisher_api_guide/publisher_excluding_recipients> for more info).
|
26
|
+
|
27
|
+
Pusher['a_channel'].trigger!('an_event', {:some => 'data'}, socket_id)
|
28
|
+
|
29
|
+
If you don't need to handle failure cases, then you can simply use the {Pusher::Channel#trigger} method, which will rescue and log any errors for you
|
30
|
+
|
31
|
+
Pusher['a_channel'].trigger('an_event', {:some => 'data'})
|
32
|
+
|
33
|
+
Logging
|
34
|
+
-------
|
35
|
+
|
36
|
+
Errors are logged to `Pusher.logger`. It will by default use `Logger` from stdlib, however you can assign any logger:
|
37
|
+
|
38
|
+
Pusher.logger = Rails.logger
|
39
|
+
|
40
|
+
Asynchronous triggering
|
41
|
+
-----------------------
|
42
|
+
|
43
|
+
To avoid blocking in a typical web application, you may wish to use the {Pusher::Channel#trigger_async} method which makes asynchronous API requests. `trigger_async` returns a deferrable which you can optionally bind to with success and failure callbacks.
|
44
|
+
|
45
|
+
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.
|
46
|
+
|
47
|
+
$ gem install em-http-request
|
48
|
+
|
49
|
+
deferrable = Pusher['a_channel'].trigger_async('an_event', {
|
50
|
+
:some => 'data'
|
51
|
+
}, socket_id)
|
52
|
+
deferrable.callback {
|
53
|
+
# Do something on success
|
54
|
+
}
|
55
|
+
deferrable.errback { |error|
|
56
|
+
# error is a instance of Pusher::Error
|
57
|
+
}
|
58
|
+
|
59
|
+
Private channels
|
60
|
+
----------------
|
61
|
+
|
62
|
+
The Pusher Gem also deals with signing requests for authenticated private channels. A quick Rails controller example:
|
63
|
+
|
64
|
+
reponse = Pusher['private-my_channel'].authenticate(params[:socket_id])
|
65
|
+
render :json => response
|
66
|
+
|
67
|
+
Read more about private channels in [the docs](http://pusher.com/docs/client_api_guide/client_channels#subscribe-private-channels) and under {Pusher::Channel#authenticate}.
|
68
|
+
|
69
|
+
Developing
|
70
|
+
----------
|
71
|
+
|
72
|
+
Use bundler in order to run specs with the correct dependencies.
|
73
|
+
|
74
|
+
bundle
|
75
|
+
bundle exec rspec spec/*_spec.rb
|
76
|
+
|
77
|
+
Copyright
|
78
|
+
---------
|
79
|
+
|
80
|
+
Copyright (c) 2010 New Bamboo. See LICENSE for details.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'pusher'
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'em-http-request'
|
5
|
+
|
6
|
+
# To get these values:
|
7
|
+
# - Go to https://app.pusherapp.com/
|
8
|
+
# - Click on Choose App.
|
9
|
+
# - Click on one of your apps
|
10
|
+
# - Click API Access
|
11
|
+
Pusher.app_id = 'your_app_id'
|
12
|
+
Pusher.key = 'your_key'
|
13
|
+
Pusher.secret = 'your_secret'
|
14
|
+
|
15
|
+
|
16
|
+
EM.run {
|
17
|
+
deferrable = Pusher['test_channel'].trigger_async('my_event', 'hi')
|
18
|
+
|
19
|
+
deferrable.callback { # called on success
|
20
|
+
puts "Message sent successfully."
|
21
|
+
EM.stop
|
22
|
+
}
|
23
|
+
deferrable.errback { |error| # called on error
|
24
|
+
puts "Message could not be sent."
|
25
|
+
puts error
|
26
|
+
EM.stop
|
27
|
+
}
|
28
|
+
}
|
@@ -0,0 +1,107 @@
|
|
1
|
+
autoload 'Logger', 'logger'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
# Used for configuring API credentials and creating Channel objects
|
5
|
+
#
|
6
|
+
module Pusher
|
7
|
+
# All Pusher errors descend from this class so you can easily rescue Pusher
|
8
|
+
# errors
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# begin
|
12
|
+
# Pusher['a_channel'].trigger!('an_event', {:some => 'data'})
|
13
|
+
# rescue Pusher::Error => e
|
14
|
+
# # Do something on error
|
15
|
+
# end
|
16
|
+
class Error < RuntimeError; end
|
17
|
+
class AuthenticationError < Error; end
|
18
|
+
class ConfigurationError < Error; end
|
19
|
+
class HTTPError < Error; attr_accessor :original_error; end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
attr_accessor :scheme, :host, :port
|
23
|
+
attr_writer :logger
|
24
|
+
attr_accessor :app_id, :key, :secret
|
25
|
+
|
26
|
+
# @private
|
27
|
+
def logger
|
28
|
+
@logger ||= begin
|
29
|
+
log = Logger.new($stdout)
|
30
|
+
log.level = Logger::INFO
|
31
|
+
log
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# @private
|
36
|
+
def authentication_token
|
37
|
+
Signature::Token.new(@key, @secret)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @private Builds a connection url for Pusherapp
|
41
|
+
def url
|
42
|
+
URI::Generic.build({
|
43
|
+
:scheme => self.scheme,
|
44
|
+
:host => self.host,
|
45
|
+
:port => self.port,
|
46
|
+
:path => "/apps/#{self.app_id}"
|
47
|
+
})
|
48
|
+
end
|
49
|
+
|
50
|
+
# Configure Pusher connection by providing a url rather than specifying
|
51
|
+
# scheme, key, secret, and app_id separately.
|
52
|
+
#
|
53
|
+
# @example
|
54
|
+
# Pusher.url = http://KEY:SECRET@api.pusherapp.com/apps/APP_ID
|
55
|
+
#
|
56
|
+
def url=(url)
|
57
|
+
uri = URI.parse(url)
|
58
|
+
self.app_id = uri.path.split('/').last
|
59
|
+
self.key = uri.user
|
60
|
+
self.secret = uri.password
|
61
|
+
self.host = uri.host
|
62
|
+
self.port = uri.port
|
63
|
+
end
|
64
|
+
|
65
|
+
# Configure whether Pusher API calls should be made over SSL
|
66
|
+
# (default false)
|
67
|
+
#
|
68
|
+
# @example
|
69
|
+
# Pusher.encrypted = true
|
70
|
+
#
|
71
|
+
def encrypted=(boolean)
|
72
|
+
Pusher.scheme = boolean ? 'https' : 'http'
|
73
|
+
# Configure port if it hasn't already been configured
|
74
|
+
Pusher.port ||= boolean ? 443 : 80
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def configured?
|
80
|
+
host && scheme && key && secret && app_id
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Defaults
|
85
|
+
self.scheme = 'http'
|
86
|
+
self.host = 'api.pusherapp.com'
|
87
|
+
|
88
|
+
if ENV['PUSHER_URL']
|
89
|
+
self.url = ENV['PUSHER_URL']
|
90
|
+
end
|
91
|
+
|
92
|
+
# Return a channel by name
|
93
|
+
#
|
94
|
+
# @example
|
95
|
+
# Pusher['my-channel']
|
96
|
+
# @return [Channel]
|
97
|
+
# @raise [ConfigurationError] unless key, secret and app_id have been
|
98
|
+
# configured
|
99
|
+
def self.[](channel_name)
|
100
|
+
raise ConfigurationError, 'Missing configuration: please check that Pusher.key, Pusher.secret and Pusher.app_id are configured.' unless configured?
|
101
|
+
@channels ||= {}
|
102
|
+
@channels[channel_name.to_s] ||= Channel.new(url, channel_name)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
require 'pusher/channel'
|
107
|
+
require 'pusher/request'
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'core_extensions'
|
2
|
+
require 'hmac-sha2'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Pusher
|
6
|
+
# Trigger events on Channels
|
7
|
+
class Channel
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
def initialize(base_url, name)
|
11
|
+
@uri = base_url.dup
|
12
|
+
@uri.path = @uri.path + "/channels/#{name}/"
|
13
|
+
@name = name
|
14
|
+
end
|
15
|
+
|
16
|
+
# Trigger event asynchronously using EventMachine::HttpRequest
|
17
|
+
#
|
18
|
+
# @param (see #trigger!)
|
19
|
+
# @return [EM::DefaultDeferrable]
|
20
|
+
# Attach a callback to be notified of success (with no parameters).
|
21
|
+
# Attach an errback to be notified of failure (with an error parameter
|
22
|
+
# which includes the HTTP status code returned)
|
23
|
+
# @raise [LoadError] unless em-http-request gem is available
|
24
|
+
# @raise [Pusher::Error] unless the eventmachine reactor is running. You
|
25
|
+
# probably want to run your application inside a server such as thin
|
26
|
+
#
|
27
|
+
def trigger_async(event_name, data, socket_id = nil, &block)
|
28
|
+
request = construct_event_request(event_name, data, socket_id)
|
29
|
+
request.send_async
|
30
|
+
end
|
31
|
+
|
32
|
+
# Trigger event
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# begin
|
36
|
+
# Pusher['my-channel'].trigger!('an_event', {:some => 'data'})
|
37
|
+
# rescue Pusher::Error => e
|
38
|
+
# # Do something on error
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# @param data [Object] Event data to be triggered in javascript.
|
42
|
+
# Objects other than strings will be converted to JSON
|
43
|
+
# @param socket_id Allows excluding a given socket_id from receiving the
|
44
|
+
# event - see http://pusher.com/docs/publisher_api_guide/publisher_excluding_recipients for more info
|
45
|
+
#
|
46
|
+
# @raise [Pusher::Error] on invalid Pusher response - see the error message for more details
|
47
|
+
# @raise [Pusher::HTTPError] on any error raised inside Net::HTTP - the original error is available in the original_error attribute
|
48
|
+
#
|
49
|
+
def trigger!(event_name, data, socket_id = nil)
|
50
|
+
request = construct_event_request(event_name, data, socket_id)
|
51
|
+
request.send_sync
|
52
|
+
end
|
53
|
+
|
54
|
+
# Trigger event, catching and logging any errors.
|
55
|
+
#
|
56
|
+
# @note CAUTION! No exceptions will be raised on failure
|
57
|
+
# @param (see #trigger!)
|
58
|
+
#
|
59
|
+
def trigger(event_name, data, socket_id = nil)
|
60
|
+
trigger!(event_name, data, socket_id)
|
61
|
+
rescue Pusher::Error => e
|
62
|
+
Pusher.logger.error("#{e.message} (#{e.class})")
|
63
|
+
Pusher.logger.debug(e.backtrace.join("\n"))
|
64
|
+
end
|
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
|
+
|
77
|
+
# Compute authentication string required to subscribe to this channel.
|
78
|
+
#
|
79
|
+
# See http://pusher.com/docs/auth_signatures for more details.
|
80
|
+
#
|
81
|
+
# @param socket_id [String] Each Pusher socket connection receives a
|
82
|
+
# unique socket_id. This is sent from pusher.js to your server when
|
83
|
+
# channel authentication is required.
|
84
|
+
# @param custom_string [String] Allows signing additional data
|
85
|
+
# @return [String]
|
86
|
+
#
|
87
|
+
def authentication_string(socket_id, custom_string = nil)
|
88
|
+
raise "Invalid socket_id" if socket_id.nil? || socket_id.empty?
|
89
|
+
raise 'Custom argument must be a string' unless custom_string.nil? || custom_string.kind_of?(String)
|
90
|
+
|
91
|
+
string_to_sign = [socket_id, name, custom_string].compact.map{|e|e.to_s}.join(':')
|
92
|
+
Pusher.logger.debug "Signing #{string_to_sign}"
|
93
|
+
token = Pusher.authentication_token
|
94
|
+
signature = HMAC::SHA256.hexdigest(token.secret, string_to_sign)
|
95
|
+
|
96
|
+
return "#{token.key}:#{signature}"
|
97
|
+
end
|
98
|
+
|
99
|
+
# Deprecated - for backward compatibility
|
100
|
+
alias :socket_auth :authentication_string
|
101
|
+
|
102
|
+
# Generate an authentication endpoint response
|
103
|
+
#
|
104
|
+
# @example Private channels
|
105
|
+
# render :json => Pusher['private-my_channel'].authenticate(params[:socket_id])
|
106
|
+
#
|
107
|
+
# @example Presence channels
|
108
|
+
# render :json => Pusher['private-my_channel'].authenticate(params[:socket_id], {
|
109
|
+
# :user_id => current_user.id, # => required
|
110
|
+
# :user_info => { # => optional - for example
|
111
|
+
# :name => current_user.name,
|
112
|
+
# :email => current_user.email
|
113
|
+
# }
|
114
|
+
# })
|
115
|
+
#
|
116
|
+
# @param socket_id [String]
|
117
|
+
# @param custom_data [Hash] used for example by private channels
|
118
|
+
#
|
119
|
+
# @return [Hash]
|
120
|
+
#
|
121
|
+
# @private Custom data is sent to server as JSON-encoded string
|
122
|
+
#
|
123
|
+
def authenticate(socket_id, custom_data = nil)
|
124
|
+
custom_data = custom_data.to_json if custom_data
|
125
|
+
auth = socket_auth(socket_id, custom_data)
|
126
|
+
r = {:auth => auth}
|
127
|
+
r[:channel_data] = custom_data if custom_data
|
128
|
+
r
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
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
|
142
|
+
else
|
143
|
+
begin
|
144
|
+
data.to_json
|
145
|
+
rescue Exception => e
|
146
|
+
Pusher.logger.error("Could not convert #{data.inspect} into JSON")
|
147
|
+
raise e
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
request = Pusher::Request.new(:post, @uri + 'events', params, body)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'signature'
|
2
|
+
require 'digest/md5'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Pusher
|
6
|
+
class Request
|
7
|
+
def initialize(verb, uri, params, body = nil, token = nil)
|
8
|
+
@verb = verb
|
9
|
+
@uri = uri
|
10
|
+
|
11
|
+
if body
|
12
|
+
@body = body
|
13
|
+
params[:body_md5] = Digest::MD5.hexdigest(body)
|
14
|
+
end
|
15
|
+
|
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"
|
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
|
51
|
+
end
|
52
|
+
|
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
|
+
}
|
80
|
+
|
81
|
+
deferrable
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def handle_response(status_code, body)
|
87
|
+
case status_code
|
88
|
+
when 200
|
89
|
+
return JSON.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
|
106
|
+
end
|
107
|
+
end
|