ably 0.8.2 → 0.8.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +185 -0
- data/LICENSE +15 -0
- data/README.md +8 -4
- data/SPEC.md +999 -531
- data/ably.gemspec +1 -1
- data/lib/ably.rb +1 -1
- data/lib/ably/auth.rb +114 -87
- data/lib/ably/exceptions.rb +40 -14
- data/lib/ably/models/message.rb +3 -5
- data/lib/ably/models/paginated_result.rb +3 -12
- data/lib/ably/models/presence_message.rb +8 -2
- data/lib/ably/models/protocol_message.rb +15 -3
- data/lib/ably/models/stat.rb +1 -1
- data/lib/ably/models/token_details.rb +1 -1
- data/lib/ably/modules/channels_collection.rb +7 -1
- data/lib/ably/modules/conversions.rb +1 -1
- data/lib/ably/modules/encodeable.rb +6 -3
- data/lib/ably/modules/message_pack.rb +2 -2
- data/lib/ably/modules/model_common.rb +1 -1
- data/lib/ably/modules/state_machine.rb +2 -2
- data/lib/ably/realtime.rb +1 -0
- data/lib/ably/realtime/auth.rb +191 -0
- data/lib/ably/realtime/channel.rb +97 -25
- data/lib/ably/realtime/channel/channel_manager.rb +11 -3
- data/lib/ably/realtime/client.rb +22 -6
- data/lib/ably/realtime/connection.rb +74 -41
- data/lib/ably/realtime/connection/connection_manager.rb +48 -33
- data/lib/ably/realtime/presence.rb +17 -3
- data/lib/ably/rest/channel.rb +43 -16
- data/lib/ably/rest/client.rb +57 -26
- data/lib/ably/rest/middleware/exceptions.rb +3 -1
- data/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +4 -2
- data/lib/ably/rest/presence.rb +1 -0
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/auth_spec.rb +242 -0
- data/spec/acceptance/realtime/channel_spec.rb +277 -5
- data/spec/acceptance/realtime/channels_spec.rb +64 -0
- data/spec/acceptance/realtime/client_spec.rb +26 -5
- data/spec/acceptance/realtime/connection_failures_spec.rb +23 -6
- data/spec/acceptance/realtime/connection_spec.rb +167 -16
- data/spec/acceptance/realtime/message_spec.rb +9 -8
- data/spec/acceptance/realtime/presence_history_spec.rb +1 -0
- data/spec/acceptance/realtime/presence_spec.rb +121 -10
- data/spec/acceptance/realtime/stats_spec.rb +13 -1
- data/spec/acceptance/rest/auth_spec.rb +161 -79
- data/spec/acceptance/rest/base_spec.rb +3 -3
- data/spec/acceptance/rest/channel_spec.rb +142 -15
- data/spec/acceptance/rest/channels_spec.rb +23 -0
- data/spec/acceptance/rest/client_spec.rb +180 -18
- data/spec/acceptance/rest/message_spec.rb +8 -8
- data/spec/acceptance/rest/presence_spec.rb +136 -25
- data/spec/acceptance/rest/stats_spec.rb +60 -4
- data/spec/shared/client_initializer_behaviour.rb +54 -3
- data/spec/unit/auth_spec.rb +7 -6
- data/spec/unit/models/message_spec.rb +1 -9
- data/spec/unit/models/paginated_result_spec.rb +1 -18
- data/spec/unit/models/presence_message_spec.rb +1 -1
- data/spec/unit/models/protocol_message_spec.rb +21 -1
- data/spec/unit/realtime/channel_spec.rb +10 -3
- data/spec/unit/realtime/channels_spec.rb +27 -8
- data/spec/unit/rest/channel_spec.rb +0 -8
- data/spec/unit/rest/client_spec.rb +7 -7
- metadata +13 -7
- data/LICENSE.txt +0 -22
data/ably.gemspec
CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_runtime_dependency 'faraday', '~> 0.9'
|
25
25
|
spec.add_runtime_dependency 'json'
|
26
26
|
spec.add_runtime_dependency 'websocket-driver', '~> 0.3'
|
27
|
-
spec.add_runtime_dependency 'msgpack', '0.6.
|
27
|
+
spec.add_runtime_dependency 'msgpack', '>= 0.6.2'
|
28
28
|
|
29
29
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
30
30
|
spec.add_development_dependency 'rake'
|
data/lib/ably.rb
CHANGED
data/lib/ably/auth.rb
CHANGED
@@ -22,44 +22,53 @@ module Ably
|
|
22
22
|
# @!attribute [r] key_secret
|
23
23
|
# @return [String] Key secret (private secure part of the API key), if present
|
24
24
|
# @!attribute [r] options
|
25
|
-
# @return [Hash] {Ably::Auth} options configured for this client
|
26
|
-
|
25
|
+
# @return [Hash] Default {Ably::Auth} options configured for this client
|
26
|
+
# @!attribute [r] token_params
|
27
|
+
# @return [Hash] Default token params used for token requests, see {#request_token}
|
28
|
+
#
|
27
29
|
class Auth
|
28
30
|
include Ably::Modules::Conversions
|
29
31
|
include Ably::Modules::HttpHelpers
|
30
32
|
|
31
33
|
# Default capability Hash object and TTL in seconds for issued tokens
|
32
34
|
TOKEN_DEFAULTS = {
|
33
|
-
capability:
|
34
|
-
ttl:
|
35
|
-
|
35
|
+
capability: { '*' => ['*'] },
|
36
|
+
ttl: 60 * 60, # 1 hour in seconds
|
37
|
+
renew_token_buffer: 10 # buffer to allow a token to be reissued before the token is considered expired (Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER)
|
38
|
+
}.freeze
|
36
39
|
|
37
|
-
attr_reader :options, :current_token_details
|
40
|
+
attr_reader :options, :token_params, :current_token_details
|
38
41
|
alias_method :auth_options, :options
|
39
42
|
|
40
43
|
# Creates an Auth object
|
41
44
|
#
|
42
45
|
# @param [Ably::Rest::Client] client {Ably::Rest::Client} this Auth object uses
|
43
|
-
# @param [Hash] options
|
44
|
-
# @
|
46
|
+
# @param [Hash] auth_options the authentication options used as a default future token requests
|
47
|
+
# @param [Hash] token_params the token params used as a default for future token requests
|
48
|
+
# @option (see #request_token)
|
45
49
|
#
|
46
|
-
def initialize(client,
|
47
|
-
|
50
|
+
def initialize(client, auth_options, token_params)
|
51
|
+
unless auth_options.kind_of?(Hash)
|
52
|
+
raise ArgumentError, 'Expected auth_options to be a Hash'
|
53
|
+
end
|
48
54
|
|
49
|
-
|
55
|
+
unless token_params.kind_of?(Hash)
|
56
|
+
raise ArgumentError, 'Expected token_params to be a Hash'
|
57
|
+
end
|
58
|
+
|
59
|
+
ensure_valid_auth_attributes auth_options
|
50
60
|
|
51
61
|
@client = client
|
52
|
-
@options = auth_options
|
62
|
+
@options = auth_options.dup
|
63
|
+
@token_params = token_params.dup
|
53
64
|
|
54
|
-
|
55
|
-
raise ArgumentError, 'Expected auth_options to be a Hash'
|
56
|
-
end
|
65
|
+
@options.delete :force # Forcing token auth for every request is not a valid default
|
57
66
|
|
58
|
-
if
|
67
|
+
if options[:key] && (options[:key_secret] || options[:key_name])
|
59
68
|
raise ArgumentError, 'key and key_name or key_secret are mutually exclusive. Provider either a key or key_name & key_secret'
|
60
69
|
end
|
61
70
|
|
62
|
-
split_api_key_into_key_and_secret!
|
71
|
+
split_api_key_into_key_and_secret! options if options[:key]
|
63
72
|
|
64
73
|
if using_basic_auth? && !api_key_present?
|
65
74
|
raise ArgumentError, 'key is missing. Either an API key, token, or token auth method must be provided'
|
@@ -71,85 +80,90 @@ module Ably
|
|
71
80
|
end
|
72
81
|
|
73
82
|
@options.freeze
|
83
|
+
@token_params.freeze
|
74
84
|
end
|
75
85
|
|
76
86
|
# Ensures valid auth credentials are present for the library instance. This may rely on an already-known and valid token, and will obtain a new token if necessary.
|
77
87
|
#
|
78
|
-
# In the event that a new token request is made, the
|
88
|
+
# In the event that a new token request is made, the provided options are used.
|
79
89
|
#
|
80
|
-
# @param [Hash]
|
81
|
-
# @
|
82
|
-
# @option
|
83
|
-
# @option
|
90
|
+
# @param [Hash] auth_options the authentication options used for future token requests
|
91
|
+
# @param [Hash] token_params the token params used for future token requests
|
92
|
+
# @option auth_options [Boolean] :force obtains a new token even if the current token is valid
|
93
|
+
# @option (see #request_token)
|
84
94
|
#
|
85
|
-
# @return (see #
|
95
|
+
# @return (see #create_token_request)
|
86
96
|
#
|
87
97
|
# @example
|
88
98
|
# # will issue a simple token request using basic auth
|
89
99
|
# client = Ably::Rest::Client.new(key: 'key.id:secret')
|
90
|
-
#
|
100
|
+
# token_details = client.auth.authorise
|
91
101
|
#
|
92
102
|
# # will use token request from block to authorise if not already authorised
|
93
|
-
#
|
103
|
+
# token_details = client.auth.authorise auth_callback: Proc.new do
|
94
104
|
# # create token_request object
|
95
105
|
# token_request
|
96
106
|
# end
|
97
107
|
#
|
98
|
-
def authorise(
|
99
|
-
ensure_valid_auth_attributes
|
108
|
+
def authorise(auth_options = {}, token_params = {})
|
109
|
+
ensure_valid_auth_attributes auth_options
|
110
|
+
|
111
|
+
auth_options = auth_options.clone
|
100
112
|
|
101
|
-
if current_token_details && !
|
113
|
+
if current_token_details && !auth_options.delete(:force)
|
102
114
|
return current_token_details unless current_token_details.expired?
|
103
115
|
end
|
104
116
|
|
105
|
-
|
106
|
-
|
107
|
-
|
117
|
+
split_api_key_into_key_and_secret! auth_options if auth_options[:key]
|
118
|
+
@options = @options.merge(auth_options) # update defaults
|
119
|
+
|
120
|
+
token_params = (auth_options.delete(:token_params) || {}).merge(token_params)
|
121
|
+
@token_params = @token_params.merge(token_params) # update defaults
|
108
122
|
|
109
|
-
@current_token_details = request_token(
|
123
|
+
@current_token_details = request_token(auth_options, token_params)
|
110
124
|
end
|
111
125
|
|
112
126
|
# Request a {Ably::Models::TokenDetails} which can be used to make authenticated token based requests
|
113
127
|
#
|
114
|
-
# @param [Hash]
|
115
|
-
# @option
|
116
|
-
# @option
|
117
|
-
# @option
|
118
|
-
# @option
|
119
|
-
# @option
|
120
|
-
#
|
121
|
-
# @
|
122
|
-
#
|
123
|
-
# @option options [Integer] :ttl validity time in seconds for the requested {Ably::Models::TokenDetails}. Limits may apply, see {https://www.ably.io/documentation/other/authentication}
|
124
|
-
# @option options [Hash] :capability canonicalised representation of the resource paths and associated operations
|
125
|
-
# @option options [Boolean] :query_time when true will query the {https://www.ably.io Ably} system for the current time instead of using the local time
|
126
|
-
# @option options [Time] :timestamp the time of the of the request
|
127
|
-
# @option options [String] :nonce an unquoted, unescaped random string of at least 16 characters
|
128
|
+
# @param [Hash] auth_options (see #create_token_request)
|
129
|
+
# @option auth_options [String] :auth_url a URL to be used to GET or POST a set of token request params, to obtain a signed token request
|
130
|
+
# @option auth_options [Hash] :auth_headers a set of application-specific headers to be added to any request made to the +auth_url+
|
131
|
+
# @option auth_options [Hash] :auth_params a set of application-specific query params to be added to any request made to the +auth_url+
|
132
|
+
# @option auth_options [Symbol] :auth_method (:get) HTTP method to use with +auth_url+, must be either +:get+ or +:post+
|
133
|
+
# @option auth_options [Proc] :auth_callback when provided, the Proc will be called with the token params hash as the first argument, whenever a new token is required.
|
134
|
+
# The Proc should return a token string, {Ably::Models::TokenDetails} or JSON equivalent, {Ably::Models::TokenRequest} or JSON equivalent
|
135
|
+
# @param [Hash] token_params (see #create_token_request)
|
136
|
+
# @option (see #create_token_request)
|
128
137
|
#
|
129
138
|
# @return [Ably::Models::TokenDetails]
|
130
139
|
#
|
131
140
|
# @example
|
132
141
|
# # simple token request using basic auth
|
133
142
|
# client = Ably::Rest::Client.new(key: 'key.id:secret')
|
134
|
-
#
|
143
|
+
# token_details = client.auth.request_token
|
144
|
+
#
|
145
|
+
# # token request with token params
|
146
|
+
# client.auth.request_token token_params: { ttl: 1.hour }
|
135
147
|
#
|
136
148
|
# # token request using auth block
|
137
|
-
#
|
149
|
+
# token_details = client.auth.request_token auth_callback: Proc.new do
|
138
150
|
# # create token_request object
|
139
151
|
# token_request
|
140
152
|
# end
|
141
153
|
#
|
142
|
-
def request_token(
|
143
|
-
ensure_valid_auth_attributes
|
154
|
+
def request_token(auth_options = {}, token_params = {})
|
155
|
+
ensure_valid_auth_attributes auth_options
|
144
156
|
|
145
|
-
|
157
|
+
token_params = (auth_options[:token_params] || {}).merge(token_params)
|
158
|
+
token_params = self.token_params.merge(token_params)
|
159
|
+
auth_options = self.options.merge(auth_options)
|
146
160
|
|
147
|
-
token_request = if auth_callback =
|
148
|
-
auth_callback.call(
|
149
|
-
elsif auth_url =
|
150
|
-
token_request_from_auth_url(auth_url,
|
161
|
+
token_request = if auth_callback = auth_options.delete(:auth_callback)
|
162
|
+
auth_callback.call(token_params)
|
163
|
+
elsif auth_url = auth_options.delete(:auth_url)
|
164
|
+
token_request_from_auth_url(auth_url, auth_options)
|
151
165
|
else
|
152
|
-
create_token_request(
|
166
|
+
create_token_request(auth_options, token_params)
|
153
167
|
end
|
154
168
|
|
155
169
|
case token_request
|
@@ -172,19 +186,23 @@ module Ably
|
|
172
186
|
|
173
187
|
# Creates and signs a token request that can then subsequently be used by any client to request a token
|
174
188
|
#
|
175
|
-
# @param [Hash]
|
176
|
-
# @option
|
177
|
-
# @option
|
178
|
-
# @option
|
179
|
-
# @option
|
180
|
-
#
|
181
|
-
# @
|
182
|
-
# @option
|
189
|
+
# @param [Hash] auth_options the authentication options for the token request
|
190
|
+
# @option auth_options [String] :key API key comprising the key name and key secret in a single string
|
191
|
+
# @option auth_options [String] :client_id client ID identifying this connection to other clients (will use +client_id+ specified when library was instanced if provided)
|
192
|
+
# @option auth_options [Boolean] :query_time when true will query the {https://www.ably.io Ably} system for the current time instead of using the local time
|
193
|
+
# @option auth_options [Hash] :token_params convenience to pass in +token_params+ within the +auth_options+ argument, this helps avoid the following +authorise({key: key}, {ttl: 23})+ by allowing +authorise(key:key,token_params:{ttl:23})+
|
194
|
+
#
|
195
|
+
# @param [Hash] token_params the token params used in the token request
|
196
|
+
# @option token_params [String] :client_id A client ID to associate with this token. The generated token may be used to authenticate as this +client_id+
|
197
|
+
# @option token_params [Integer] :ttl validity time in seconds for the requested {Ably::Models::TokenDetails}. Limits may apply, see {https://www.ably.io/documentation/other/authentication}
|
198
|
+
# @option token_params [Hash] :capability canonicalised representation of the resource paths and associated operations
|
199
|
+
# @option token_params [Time] :timestamp the time of the request
|
200
|
+
# @option token_params [String] :nonce an unquoted, unescaped random string of at least 16 characters
|
183
201
|
#
|
184
202
|
# @return [Models::TokenRequest]
|
185
203
|
#
|
186
204
|
# @example
|
187
|
-
# client.auth.create_token_request(id: 'asd.asd', ttl: 3600)
|
205
|
+
# client.auth.create_token_request(id: 'asd.asd', token_params: { ttl: 3600 })
|
188
206
|
# #<Ably::Models::TokenRequest:0x007fd5d919df78
|
189
207
|
# # @hash={
|
190
208
|
# # :id=>"asds.adsa",
|
@@ -196,30 +214,37 @@ module Ably
|
|
196
214
|
# # :mac=>"881oZHeFo6oMim7....uE56a8gUxHw="
|
197
215
|
# # }
|
198
216
|
# #>>
|
199
|
-
def create_token_request(
|
200
|
-
ensure_valid_auth_attributes
|
217
|
+
def create_token_request(auth_options = {}, token_params = {})
|
218
|
+
ensure_valid_auth_attributes auth_options
|
201
219
|
|
202
|
-
|
220
|
+
auth_options = auth_options.clone
|
221
|
+
token_params = (auth_options[:token_params] || {}).merge(token_params)
|
203
222
|
|
204
|
-
split_api_key_into_key_and_secret!
|
205
|
-
request_key_name =
|
206
|
-
request_key_secret =
|
207
|
-
raise Ably::Exceptions::TokenRequestError, 'Key Name and Key Secret are required to generate a new token request' unless request_key_name && request_key_secret
|
223
|
+
split_api_key_into_key_and_secret! auth_options if auth_options[:key]
|
224
|
+
request_key_name = auth_options.delete(:key_name) || key_name
|
225
|
+
request_key_secret = auth_options.delete(:key_secret) || key_secret
|
208
226
|
|
209
|
-
|
227
|
+
raise Ably::Exceptions::TokenRequestFailed, 'Key Name and Key Secret are required to generate a new token request' unless request_key_name && request_key_secret
|
228
|
+
|
229
|
+
timestamp = if auth_options[:query_time]
|
210
230
|
client.time
|
211
231
|
else
|
212
|
-
|
232
|
+
token_params.delete(:timestamp) || Time.now
|
213
233
|
end
|
214
234
|
timestamp = Time.at(timestamp) if timestamp.kind_of?(Integer)
|
215
235
|
|
236
|
+
ttl = [
|
237
|
+
(token_params[:ttl] || TOKEN_DEFAULTS.fetch(:ttl)),
|
238
|
+
Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER + TOKEN_DEFAULTS.fetch(:renew_token_buffer) # never issue a token that will be immediately considered expired due to the buffer
|
239
|
+
].max
|
240
|
+
|
216
241
|
token_request = {
|
217
|
-
keyName:
|
218
|
-
clientId:
|
219
|
-
ttl: (
|
242
|
+
keyName: request_key_name,
|
243
|
+
clientId: token_params[:client_id] || auth_options[:client_id] || client_id,
|
244
|
+
ttl: (ttl * 1000).to_i,
|
220
245
|
timestamp: (timestamp.to_f * 1000).round,
|
221
|
-
capability:
|
222
|
-
nonce:
|
246
|
+
capability: token_params[:capability] || TOKEN_DEFAULTS.fetch(:capability),
|
247
|
+
nonce: token_params[:nonce] || SecureRandom.hex.force_encoding('UTF-8')
|
223
248
|
}
|
224
249
|
|
225
250
|
token_request[:capability] = JSON.dump(token_request[:capability]) if token_request[:capability].is_a?(Hash)
|
@@ -227,7 +252,7 @@ module Ably
|
|
227
252
|
token_request[:mac] = sign_params(token_request, request_key_secret)
|
228
253
|
|
229
254
|
# Undocumented feature to request a persisted token
|
230
|
-
token_request[:persisted] =
|
255
|
+
token_request[:persisted] = token_params[:persisted] if token_params[:persisted]
|
231
256
|
|
232
257
|
Models::TokenRequest.new(token_request)
|
233
258
|
end
|
@@ -252,7 +277,7 @@ module Ably
|
|
252
277
|
# True when Token Auth is being used to authenticate with Ably
|
253
278
|
def using_token_auth?
|
254
279
|
return options[:use_token_auth] if options.has_key?(:use_token_auth)
|
255
|
-
token || current_token_details || has_client_id? || token_creatable_externally?
|
280
|
+
!!(token || current_token_details || has_client_id? || token_creatable_externally?)
|
256
281
|
end
|
257
282
|
|
258
283
|
def client_id
|
@@ -270,6 +295,7 @@ module Ably
|
|
270
295
|
end
|
271
296
|
|
272
297
|
# Auth header string used in HTTP requests to Ably
|
298
|
+
# Will reauthorise implicitly if required and capable
|
273
299
|
#
|
274
300
|
# @return [String] HTTP authentication value used in HTTP_AUTHORIZATION header
|
275
301
|
def auth_header
|
@@ -281,6 +307,7 @@ module Ably
|
|
281
307
|
end
|
282
308
|
|
283
309
|
# Auth params used in URI endpoint for Realtime connections
|
310
|
+
# Will reauthorise implicitly if required and capable
|
284
311
|
#
|
285
312
|
# @return [Hash] Auth params for a new Realtime connection
|
286
313
|
def auth_params
|
@@ -353,7 +380,7 @@ module Ably
|
|
353
380
|
end
|
354
381
|
|
355
382
|
def ensure_api_key_sent_over_secure_connection
|
356
|
-
raise Ably::Exceptions::
|
383
|
+
raise Ably::Exceptions::InsecureRequest, 'Cannot use Basic Auth over non-TLS connections' unless authentication_security_requirements_met?
|
357
384
|
end
|
358
385
|
|
359
386
|
# Basic Auth HTTP Authorization header value
|
@@ -424,18 +451,18 @@ module Ably
|
|
424
451
|
# Retrieve a token request from a specified URL, expects a JSON response
|
425
452
|
#
|
426
453
|
# @return [Hash]
|
427
|
-
def token_request_from_auth_url(auth_url,
|
454
|
+
def token_request_from_auth_url(auth_url, auth_options)
|
428
455
|
uri = URI.parse(auth_url)
|
429
456
|
connection = Faraday.new("#{uri.scheme}://#{uri.host}", connection_options)
|
430
|
-
method =
|
457
|
+
method = auth_options[:auth_method] || :get
|
431
458
|
|
432
459
|
response = connection.send(method) do |request|
|
433
460
|
request.url uri.path
|
434
|
-
request.params =
|
435
|
-
request.headers =
|
461
|
+
request.params = CGI.parse(uri.query || '').merge(auth_options[:auth_params] || {})
|
462
|
+
request.headers = auth_options[:auth_headers] || {}
|
436
463
|
end
|
437
464
|
|
438
|
-
if !response.body.kind_of?(Hash) && response.headers['Content-Type']
|
465
|
+
if !response.body.kind_of?(Hash) && !response.headers['Content-Type'].to_s.match(%r{text/plain}i)
|
439
466
|
raise Ably::Exceptions::InvalidResponseBody,
|
440
467
|
"Content Type #{response.headers['Content-Type']} is not supported by this client library"
|
441
468
|
end
|
data/lib/ably/exceptions.rb
CHANGED
@@ -16,14 +16,22 @@ module Ably
|
|
16
16
|
@status = status
|
17
17
|
@code = code
|
18
18
|
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
message = [super]
|
22
|
+
if status || code
|
23
|
+
additional_info = []
|
24
|
+
additional_info << "code: #{code}" if code
|
25
|
+
additional_info << "http status: #{status}" if status
|
26
|
+
message << "(#{additional_info.join(', ')})"
|
27
|
+
end
|
28
|
+
message.join(' ')
|
29
|
+
end
|
19
30
|
end
|
20
31
|
|
21
32
|
# An invalid request was received by Ably
|
22
33
|
class InvalidRequest < BaseAblyException; end
|
23
34
|
|
24
|
-
# The token is invalid
|
25
|
-
class InvalidToken < BaseAblyException; end
|
26
|
-
|
27
35
|
# Ably Protocol message received that is invalid
|
28
36
|
class ProtocolError < BaseAblyException; end
|
29
37
|
|
@@ -39,19 +47,28 @@ module Ably
|
|
39
47
|
super message, status, code
|
40
48
|
@base_error = base_error
|
41
49
|
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
message = [super]
|
53
|
+
message << "#{@base_error}" if @base_error
|
54
|
+
message.join(' < ')
|
55
|
+
end
|
42
56
|
end
|
43
57
|
|
44
58
|
# Connection Timeout accessing Realtime or REST service
|
45
|
-
class
|
59
|
+
class ConnectionTimeout < ConnectionError; end
|
46
60
|
|
47
61
|
# Connection closed unexpectedly
|
48
|
-
class
|
62
|
+
class ConnectionClosed < ConnectionError; end
|
49
63
|
|
50
|
-
#
|
51
|
-
class
|
64
|
+
# Connection suspended
|
65
|
+
class ConnectionSuspended < ConnectionError; end
|
52
66
|
|
53
|
-
#
|
54
|
-
class
|
67
|
+
# Connection failed
|
68
|
+
class ConnectionFailed < ConnectionError; end
|
69
|
+
|
70
|
+
# Invalid State Change error on a {https://github.com/gocardless/statesman Statesman State Machine}
|
71
|
+
class InvalidStateChange < BaseAblyException; end
|
55
72
|
|
56
73
|
# A generic Ably exception taht supports a status & code.
|
57
74
|
# See https://github.com/ably/ably-common/blob/master/protocol/errors.json for a list of Ably errors
|
@@ -61,21 +78,30 @@ module Ably
|
|
61
78
|
class ServerError < BaseAblyException; end
|
62
79
|
|
63
80
|
# PaginatedResult cannot retrieve the page
|
64
|
-
class
|
81
|
+
class PageMissing < BaseAblyException; end
|
65
82
|
|
66
83
|
# The expected response from the server was invalid
|
67
84
|
class InvalidResponseBody < BaseAblyException; end
|
68
85
|
|
69
86
|
# The request cannot be performed because it is insecure
|
70
|
-
class
|
87
|
+
class InsecureRequest < BaseAblyException; end
|
71
88
|
|
72
89
|
# The token request could not be created
|
73
|
-
class
|
90
|
+
class TokenRequestFailed < BaseAblyException; end
|
91
|
+
|
92
|
+
# The token has expired
|
93
|
+
class TokenExpired < BaseAblyException; end
|
74
94
|
|
75
95
|
# The message could not be delivered to the server
|
76
|
-
class
|
96
|
+
class MessageDeliveryFailed < BaseAblyException; end
|
97
|
+
|
98
|
+
# The client has been configured to not queue messages i.e. only publish down an active connection
|
99
|
+
class MessageQueueingDisabled < BaseAblyException; end
|
77
100
|
|
78
101
|
# The data payload type is not supported
|
79
|
-
class
|
102
|
+
class UnsupportedDataType < BaseAblyException; end
|
103
|
+
|
104
|
+
# When a channel is detached / failed, certain operations are not permitted such as publishing messages
|
105
|
+
class ChannelInactive < BaseAblyException; end
|
80
106
|
end
|
81
107
|
end
|