ably-rest 0.8.6 → 0.8.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/SPEC.md +1049 -1001
- data/lib/submodules/ably-ruby/CHANGELOG.md +75 -3
- data/lib/submodules/ably-ruby/LICENSE +2 -2
- data/lib/submodules/ably-ruby/README.md +81 -20
- data/lib/submodules/ably-ruby/SPEC.md +1209 -693
- data/lib/submodules/ably-ruby/ably.gemspec +4 -4
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +13 -4
- data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +10 -1
- data/lib/submodules/ably-ruby/lib/ably/logger.rb +3 -1
- data/lib/submodules/ably-ruby/lib/ably/models/cipher_params.rb +114 -0
- data/lib/submodules/ably-ruby/lib/ably/models/connection_details.rb +10 -7
- data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +3 -3
- data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +28 -21
- data/lib/submodules/ably-ruby/lib/ably/models/message.rb +19 -17
- data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/cipher.rb +10 -9
- data/lib/submodules/ably-ruby/lib/ably/models/paginated_result.rb +27 -1
- data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +20 -18
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +26 -19
- data/lib/submodules/ably-ruby/lib/ably/models/{stat.rb → stats.rb} +21 -19
- data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +14 -12
- data/lib/submodules/ably-ruby/lib/ably/models/token_request.rb +16 -14
- data/lib/submodules/ably-ruby/lib/ably/modules/async_wrapper.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/channels_collection.rb +11 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/encodeable.rb +10 -10
- data/lib/submodules/ably-ruby/lib/ably/modules/enum.rb +18 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb +3 -3
- data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +13 -5
- data/lib/submodules/ably-ruby/lib/ably/modules/safe_deferrable.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/safe_yield.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +8 -8
- data/lib/submodules/ably-ruby/lib/ably/modules/statesman_monkey_patch.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/uses_state_machine.rb +4 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime.rb +1 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +6 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +7 -6
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +7 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +7 -12
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +9 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +7 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +19 -8
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +16 -9
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +12 -3
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +35 -64
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +23 -9
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +9 -10
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/exceptions.rb +16 -4
- data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +7 -5
- data/lib/submodules/ably-ruby/lib/ably/util/crypto.rb +50 -40
- data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +4 -4
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +2 -4
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +46 -8
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +20 -20
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +7 -7
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +114 -111
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +9 -9
- data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +5 -5
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/rest/encoders_spec.rb +4 -4
- data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +15 -15
- data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +4 -4
- data/lib/submodules/ably-ruby/spec/shared/model_behaviour.rb +7 -7
- data/lib/submodules/ably-ruby/spec/shared/safe_deferrable_behaviour.rb +4 -4
- data/lib/submodules/ably-ruby/spec/unit/models/cipher_params_spec.rb +140 -0
- data/lib/submodules/ably-ruby/spec/unit/models/idiomatic_ruby_wrapper_spec.rb +15 -8
- data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/cipher_spec.rb +28 -22
- data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/json_spec.rb +24 -0
- data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +3 -3
- data/lib/submodules/ably-ruby/spec/unit/models/token_details_spec.rb +20 -18
- data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +2 -2
- data/lib/submodules/ably-ruby/spec/unit/modules/state_emitter_spec.rb +6 -6
- data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +4 -4
- data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/presence_spec.rb +5 -5
- data/lib/submodules/ably-ruby/spec/unit/util/crypto_spec.rb +50 -17
- metadata +5 -3
@@ -60,8 +60,8 @@ module Ably::Realtime
|
|
60
60
|
# Get the list of presence members
|
61
61
|
#
|
62
62
|
# @param [Hash,String] options an options Hash to filter members
|
63
|
-
# @option options [String] :client_id optional client_id for the member
|
64
|
-
# @option options [String] :connection_id optional connection_id for the member
|
63
|
+
# @option options [String] :client_id optional client_id filter for the member
|
64
|
+
# @option options [String] :connection_id optional connection_id filter for the member
|
65
65
|
# @option options [String] :wait_for_sync defaults to false, if true the get method waits for the initial presence sync following channel attachment to complete before returning the members present
|
66
66
|
#
|
67
67
|
# @yield [Array<Ably::Models::PresenceMessage>] array of present members
|
@@ -99,12 +99,12 @@ module Ably::Realtime
|
|
99
99
|
end
|
100
100
|
|
101
101
|
reset_callbacks = proc do
|
102
|
-
off
|
103
|
-
off
|
104
|
-
channel.off
|
102
|
+
off(&in_sync_callback)
|
103
|
+
off(&failed_callback)
|
104
|
+
channel.off(&failed_callback)
|
105
105
|
end
|
106
106
|
|
107
|
-
once
|
107
|
+
once(:in_sync, &in_sync_callback)
|
108
108
|
|
109
109
|
once(:failed, &failed_callback)
|
110
110
|
channel.unsafe_once(:detaching, :detached, :failed) do |error_reason|
|
@@ -131,7 +131,21 @@ module Ably::Realtime
|
|
131
131
|
end
|
132
132
|
|
133
133
|
private
|
134
|
-
|
134
|
+
def members
|
135
|
+
@members
|
136
|
+
end
|
137
|
+
|
138
|
+
def sync_serial
|
139
|
+
@sync_serial
|
140
|
+
end
|
141
|
+
|
142
|
+
def presence
|
143
|
+
@presence
|
144
|
+
end
|
145
|
+
|
146
|
+
def absent_member_cleanup_queue
|
147
|
+
@absent_member_cleanup_queue
|
148
|
+
end
|
135
149
|
|
136
150
|
def channel
|
137
151
|
presence.channel
|
@@ -156,9 +170,9 @@ module Ably::Realtime
|
|
156
170
|
end
|
157
171
|
|
158
172
|
resume_sync_proc = method(:resume_sync).to_proc
|
159
|
-
connection.on_resume
|
173
|
+
connection.on_resume(&resume_sync_proc)
|
160
174
|
once(:in_sync, :failed) do
|
161
|
-
connection.off_resume
|
175
|
+
connection.off_resume(&resume_sync_proc)
|
162
176
|
end
|
163
177
|
|
164
178
|
once(:in_sync) do
|
@@ -19,8 +19,7 @@ module Ably
|
|
19
19
|
# @param client [Ably::Rest::Client]
|
20
20
|
# @param name [String] The name of the channel
|
21
21
|
# @param channel_options [Hash] Channel options, currently reserved for Encryption options
|
22
|
-
# @option channel_options [
|
23
|
-
# @option channel_options [Hash] :cipher_params A hash of options to configure the encryption. *:key* is required, all other options are optional. See {Ably::Util::Crypto#initialize} for a list of +cipher_params+ options
|
22
|
+
# @option channel_options [Hash,Ably::Models::CipherParams] :cipher A hash of options or a {Ably::Models::CipherParams} to configure the encryption. *:key* is required, all other options are optional. See {Ably::Util::Crypto#initialize} for a list of +:cipher+ options
|
24
23
|
#
|
25
24
|
def initialize(client, name, channel_options = {})
|
26
25
|
ensure_utf_8 :name, name
|
@@ -65,15 +64,15 @@ module Ably
|
|
65
64
|
end
|
66
65
|
|
67
66
|
payload = messages.map do |message|
|
68
|
-
Ably::Models::Message(message.dup).tap do |
|
69
|
-
|
67
|
+
Ably::Models::Message(message.dup).tap do |msg|
|
68
|
+
msg.encode self
|
70
69
|
|
71
|
-
next if
|
72
|
-
if
|
70
|
+
next if msg.client_id.nil?
|
71
|
+
if msg.client_id == '*'
|
73
72
|
raise Ably::Exceptions::IncompatibleClientId.new('Wildcard client_id is reserved and cannot be used when publishing messages', 400, 40012)
|
74
73
|
end
|
75
|
-
unless client.auth.can_assume_client_id?(
|
76
|
-
raise Ably::Exceptions::IncompatibleClientId.new("Cannot publish with client_id '#{
|
74
|
+
unless client.auth.can_assume_client_id?(msg.client_id)
|
75
|
+
raise Ably::Exceptions::IncompatibleClientId.new("Cannot publish with client_id '#{msg.client_id}' as it is incompatible with the current configured client_id '#{client.client_id}'", 400, 40012)
|
77
76
|
end
|
78
77
|
end.as_json
|
79
78
|
end
|
@@ -111,8 +110,8 @@ module Ably
|
|
111
110
|
response = client.get(url, options)
|
112
111
|
|
113
112
|
Ably::Models::PaginatedResult.new(response, url, client, paginated_options) do |message|
|
114
|
-
message.tap do |
|
115
|
-
decode_message
|
113
|
+
message.tap do |msg|
|
114
|
+
decode_message msg
|
116
115
|
end
|
117
116
|
end
|
118
117
|
end
|
@@ -315,7 +315,7 @@ module Ably
|
|
315
315
|
#
|
316
316
|
# @api private
|
317
317
|
def fallback_connection
|
318
|
-
unless @fallback_connections
|
318
|
+
unless defined?(@fallback_connections) && @fallback_connections
|
319
319
|
@fallback_connections = Ably::FALLBACK_HOSTS.shuffle.map { |host| Faraday.new(endpoint_for_host(host).to_s, connection_options) }
|
320
320
|
end
|
321
321
|
@fallback_index ||= 0
|
@@ -7,6 +7,8 @@ module Ably
|
|
7
7
|
# HTTP exceptions raised by Ably due to an error status code
|
8
8
|
# Ably returns JSON/Msgpack error codes and messages so include this if possible in the exception messages
|
9
9
|
class Exceptions < Faraday::Response::Middleware
|
10
|
+
TOKEN_EXPIRED_CODE = 40140..40149
|
11
|
+
|
10
12
|
def on_complete(env)
|
11
13
|
if env.status >= 400
|
12
14
|
error_status_code = env.status
|
@@ -28,12 +30,22 @@ module Ably
|
|
28
30
|
|
29
31
|
message = 'Unknown server error' if message.to_s.strip == ''
|
30
32
|
|
33
|
+
exception_args = [message, error_status_code, error_code]
|
34
|
+
|
31
35
|
if env.status >= 500
|
32
|
-
raise Ably::Exceptions::ServerError.new(
|
33
|
-
elsif env.status == 401
|
34
|
-
|
36
|
+
raise Ably::Exceptions::ServerError.new(*exception_args)
|
37
|
+
elsif env.status == 401
|
38
|
+
if TOKEN_EXPIRED_CODE.include?(error_code)
|
39
|
+
raise Ably::Exceptions::TokenExpired.new(*exception_args)
|
40
|
+
else
|
41
|
+
raise Ably::Exceptions::UnauthorizedRequest.new(*exception_args)
|
42
|
+
end
|
43
|
+
elsif env.status == 403
|
44
|
+
raise Ably::Exceptions::ForbiddenRequest.new(*exception_args)
|
45
|
+
elsif env.status == 404
|
46
|
+
raise Ably::Exceptions::ResourceMissing.new(*exception_args)
|
35
47
|
else
|
36
|
-
raise Ably::Exceptions::InvalidRequest.new(
|
48
|
+
raise Ably::Exceptions::InvalidRequest.new(*exception_args)
|
37
49
|
end
|
38
50
|
end
|
39
51
|
end
|
@@ -23,7 +23,9 @@ module Ably
|
|
23
23
|
# Obtain the set of members currently present for a channel
|
24
24
|
#
|
25
25
|
# @param [Hash] options the options for the set of members present
|
26
|
-
# @option options [Integer]
|
26
|
+
# @option options [Integer] :limit Maximum number of members to retrieve up to 1,000, defaults to 100
|
27
|
+
# @option options [String] :client_id optional client_id filter for the member
|
28
|
+
# @option options [String] :connection_id optional connection_id filter for the member
|
27
29
|
#
|
28
30
|
# @return [Ably::Models::PaginatedResult<Ably::Models::PresenceMessage>] First {Ably::Models::PaginatedResult page} of {Ably::Models::PresenceMessage} objects accessible with {Ably::Models::PaginatedResult#items #items}.
|
29
31
|
#
|
@@ -40,8 +42,8 @@ module Ably
|
|
40
42
|
response = client.get(base_path, options)
|
41
43
|
|
42
44
|
Ably::Models::PaginatedResult.new(response, base_path, client, paginated_options) do |presence_message|
|
43
|
-
presence_message.tap do |
|
44
|
-
decode_message
|
45
|
+
presence_message.tap do |message|
|
46
|
+
decode_message message
|
45
47
|
end
|
46
48
|
end
|
47
49
|
end
|
@@ -74,8 +76,8 @@ module Ably
|
|
74
76
|
response = client.get(url, options)
|
75
77
|
|
76
78
|
Ably::Models::PaginatedResult.new(response, url, client, paginated_options) do |presence_message|
|
77
|
-
presence_message.tap do |
|
78
|
-
decode_message
|
79
|
+
presence_message.tap do |message|
|
80
|
+
decode_message message
|
79
81
|
end
|
80
82
|
end
|
81
83
|
end
|
@@ -4,52 +4,65 @@ require 'openssl'
|
|
4
4
|
module Ably::Util
|
5
5
|
class Crypto
|
6
6
|
DEFAULTS = {
|
7
|
-
algorithm: '
|
8
|
-
mode: '
|
9
|
-
key_length:
|
7
|
+
algorithm: 'aes',
|
8
|
+
mode: 'cbc',
|
9
|
+
key_length: 256,
|
10
10
|
}
|
11
11
|
|
12
12
|
BLOCK_LENGTH = 16
|
13
13
|
|
14
|
-
# Configured
|
14
|
+
# Configured {Ably::Models::CipherParams} for this Crypto object, see {#initialize} for a list of configureable options
|
15
15
|
#
|
16
|
-
# @return [
|
17
|
-
attr_reader :
|
16
|
+
# @return [Ably::Models::CipherParams]
|
17
|
+
attr_reader :cipher_params
|
18
18
|
|
19
19
|
# Creates a {Ably::Util::Crypto} object
|
20
20
|
#
|
21
|
-
# @param [Hash]
|
22
|
-
# @option
|
23
|
-
# @option options [String] :algorithm optional (default AES), specify the encryption algorithm supported by {http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html OpenSSL::Cipher}
|
24
|
-
# @option options [String] :mode optional (default CBC), specify the cipher mode supported by {http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html OpenSSL::Cipher}
|
25
|
-
# @option options [Integer] :key_length optional (default 128), specify the key length of the cipher supported by {http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html OpenSSL::Cipher}
|
26
|
-
# @option options [String] :combined optional (default AES-128-CBC), specify in one option the algorithm, key length and cipher of the cipher supported by {http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html OpenSSL::Cipher}
|
21
|
+
# @param [Hash] params a Hash used to configure the Crypto library's {Ably::Models::CipherParams}
|
22
|
+
# @option params (see Ably::Models::CipherParams#initialize)
|
27
23
|
#
|
28
24
|
# @return [Ably::Util::Crypto]
|
29
25
|
#
|
30
26
|
# @example
|
31
|
-
#
|
27
|
+
# key = Ably::Util::Crypto.generate_random_key
|
28
|
+
# crypto = Ably::Util::Crypto.new(key: key)
|
32
29
|
# encrypted = crypto.encrypt('secret text')
|
33
30
|
# crypto.decrypt(decrypted) # => 'secret text'
|
34
31
|
#
|
35
|
-
def initialize(
|
36
|
-
|
37
|
-
@
|
32
|
+
def initialize(params)
|
33
|
+
@fixed_iv = params.delete(:fixed_iv) if params.kind_of?(Hash)
|
34
|
+
@cipher_params = Ably::Models::CipherParams(params)
|
38
35
|
end
|
39
36
|
|
40
|
-
# Obtain a default CipherParams. This uses default algorithm, mode and
|
41
|
-
# padding and key length.
|
42
|
-
# system SecureRandom; the key may be obtained from the returned CipherParams
|
37
|
+
# Obtain a default {Ably::Models::CipherParams}. This uses default algorithm, mode and
|
38
|
+
# padding and key length. An IV is generated using the default
|
39
|
+
# system SecureRandom; the key may be obtained from the returned {Ably::Models::CipherParams}
|
43
40
|
# for out-of-band distribution to other clients.
|
41
|
+
|
42
|
+
# @param [Hash] params a Hash used to configure the Crypto library's {Ably::Models::CipherParams}
|
43
|
+
# @option params (see Ably::Models::CipherParams#initialize)
|
44
|
+
#
|
45
|
+
# @return [Ably::Models::CipherParams] Configured cipher params with :key, :algorithm, :mode, :key_length attributes
|
46
|
+
#
|
47
|
+
def self.get_default_params(params = {})
|
48
|
+
Ably::Models::CipherParams(params)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Generate a random encryption key from the supplied keylength (or the
|
52
|
+
# default key_length of 256 if none supplied)
|
44
53
|
#
|
45
|
-
# @
|
54
|
+
# @param [Integer] key_length Optional (default 256) key length for the generated random key. 128 and 256 bit key lengths are supported
|
55
|
+
# @return Binary String (byte array) with ASCII_8BIT encoding
|
46
56
|
#
|
47
|
-
def self.
|
48
|
-
params = DEFAULTS.merge(
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
57
|
+
def self.generate_random_key(key_length = DEFAULTS.fetch(:key_length))
|
58
|
+
params = DEFAULTS.merge(key_length: key_length)
|
59
|
+
OpenSSL::Cipher.new(cipher_type(params)).random_key
|
60
|
+
end
|
61
|
+
|
62
|
+
# The Cipher algorithm string such as AES-128-CBC
|
63
|
+
# @api private
|
64
|
+
def self.cipher_type(options)
|
65
|
+
Ably::Models::CipherParams.cipher_type(options)
|
53
66
|
end
|
54
67
|
|
55
68
|
# Encrypt payload using configured Cipher
|
@@ -58,13 +71,13 @@ module Ably::Util
|
|
58
71
|
# @param [Hash] encrypt_options an options Hash to configure the encrypt action
|
59
72
|
# @option encrypt_options [String] :iv optionally use the provided Initialization Vector instead of a randomly generated IV
|
60
73
|
#
|
61
|
-
# @return [String] binary string with
|
74
|
+
# @return [String] binary string with +Encoding::ASCII_8BIT+ encoding
|
62
75
|
#
|
63
76
|
def encrypt(payload, encrypt_options = {})
|
64
77
|
cipher = openssl_cipher
|
65
78
|
cipher.encrypt
|
66
79
|
cipher.key = key
|
67
|
-
iv = encrypt_options[:iv] ||
|
80
|
+
iv = encrypt_options[:iv] || fixed_iv || cipher.random_iv
|
68
81
|
cipher.iv = iv
|
69
82
|
|
70
83
|
iv << cipher.update(payload) << cipher.final
|
@@ -90,31 +103,28 @@ module Ably::Util
|
|
90
103
|
decipher.update(encrypted_payload) << decipher.final
|
91
104
|
end
|
92
105
|
|
93
|
-
# Generate a random key
|
94
|
-
# @return [String]
|
95
|
-
def random_key
|
96
|
-
openssl_cipher.random_key
|
97
|
-
end
|
98
|
-
|
99
106
|
# Generate a random IV
|
100
107
|
# @return [String]
|
101
108
|
def random_iv
|
102
109
|
openssl_cipher.random_iv
|
103
110
|
end
|
104
111
|
|
105
|
-
|
112
|
+
private
|
113
|
+
# Used solely for tests to fix the IV instead of randomly generate one
|
114
|
+
attr_reader :fixed_iv
|
115
|
+
|
116
|
+
# Generate a random key
|
106
117
|
# @return [String]
|
107
|
-
def
|
108
|
-
|
118
|
+
def random_key
|
119
|
+
openssl_cipher.random_key
|
109
120
|
end
|
110
121
|
|
111
|
-
private
|
112
122
|
def key
|
113
|
-
|
123
|
+
cipher_params.key
|
114
124
|
end
|
115
125
|
|
116
126
|
def openssl_cipher
|
117
|
-
OpenSSL::Cipher.new(cipher_type)
|
127
|
+
@openssl_cipher ||= OpenSSL::Cipher.new(cipher_params.cipher_type)
|
118
128
|
end
|
119
129
|
end
|
120
130
|
end
|
@@ -19,7 +19,7 @@ describe Ably::Realtime::Channel, '#history', :event_machine do
|
|
19
19
|
let(:options) { { :protocol => :json } }
|
20
20
|
|
21
21
|
it 'returns a SafeDeferrable that catches exceptions in callbacks and logs them' do
|
22
|
-
channel.publish('event', payload) do
|
22
|
+
channel.publish('event', payload) do
|
23
23
|
history = channel.history
|
24
24
|
expect(history).to be_a(Ably::Util::SafeDeferrable)
|
25
25
|
history.callback do |page|
|
@@ -32,7 +32,7 @@ describe Ably::Realtime::Channel, '#history', :event_machine do
|
|
32
32
|
|
33
33
|
context 'with a single client publishing and receiving' do
|
34
34
|
it 'retrieves realtime history' do
|
35
|
-
channel.publish('event', payload) do
|
35
|
+
channel.publish('event', payload) do
|
36
36
|
channel.history do |page|
|
37
37
|
expect(page.items.length).to eql(1)
|
38
38
|
expect(page.items[0].data).to eql(payload)
|
@@ -44,8 +44,8 @@ describe Ably::Realtime::Channel, '#history', :event_machine do
|
|
44
44
|
|
45
45
|
context 'with two clients publishing messages on the same channel' do
|
46
46
|
it 'retrieves realtime history on both channels' do
|
47
|
-
channel.publish('event', payload) do
|
48
|
-
channel2.publish('event', payload) do
|
47
|
+
channel.publish('event', payload) do
|
48
|
+
channel2.publish('event', payload) do
|
49
49
|
channel.history do |page|
|
50
50
|
expect(page.items.length).to eql(2)
|
51
51
|
expect(page.items.map(&:data).uniq).to eql([payload])
|
@@ -481,8 +481,6 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
481
481
|
end
|
482
482
|
|
483
483
|
it 'retains channel subscription state' do
|
484
|
-
messages_received = false
|
485
|
-
|
486
484
|
channel.subscribe('event') do |message|
|
487
485
|
expect(message.data).to eql('message')
|
488
486
|
stop_reactor
|
@@ -712,6 +710,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
712
710
|
context 'when the Internet is up' do
|
713
711
|
before do
|
714
712
|
allow(connection).to receive(:internet_up?).and_yield(true)
|
713
|
+
@suspended = 0
|
715
714
|
end
|
716
715
|
|
717
716
|
it 'uses a fallback host on every subsequent disconnected attempt until suspended' do
|
@@ -740,14 +739,13 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
740
739
|
expect(host).to eql(expected_host)
|
741
740
|
else
|
742
741
|
expect(custom_hosts).to include(host)
|
743
|
-
fallback_hosts_used << host if @suspended
|
742
|
+
fallback_hosts_used << host if @suspended > 0
|
744
743
|
end
|
745
744
|
request += 1
|
746
745
|
raise EventMachine::ConnectionError
|
747
746
|
end
|
748
747
|
|
749
748
|
connection.on(:suspended) do
|
750
|
-
@suspended ||= 0
|
751
749
|
@suspended += 1
|
752
750
|
|
753
751
|
if @suspended > 3
|
@@ -141,7 +141,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
141
141
|
started_at = Time.now.to_f
|
142
142
|
connection.once(:disconnected) do
|
143
143
|
connection.once(:disconnected) do |connection_state_change|
|
144
|
-
expect(connection_state_change.reason.code).to eql(
|
144
|
+
expect(connection_state_change.reason.code).to eql(40142) # token expired
|
145
145
|
expect(Time.now.to_f - started_at).to be < 1000
|
146
146
|
expect(auth_requests.count).to eql(2)
|
147
147
|
stop_reactor
|
@@ -156,7 +156,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
156
156
|
started_at = Time.now.to_f
|
157
157
|
disconnect_count = 0
|
158
158
|
connection.on(:disconnected) do |connection_state_change|
|
159
|
-
expect(connection_state_change.reason.code).to eql(
|
159
|
+
expect(connection_state_change.reason.code).to eql(40142) # token expired
|
160
160
|
disconnect_count += 1
|
161
161
|
if disconnect_count == 6
|
162
162
|
expect(Time.now.to_f - started_at).to be > 4 * 0.5 # at least 4 0.5 second pauses should have happened
|
@@ -207,7 +207,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
207
207
|
expect(original_token).to_not be_expired
|
208
208
|
started_at = Time.now
|
209
209
|
connection.once(:disconnected) do |connection_state_change|
|
210
|
-
expect(connection_state_change.reason.code).to eq(
|
210
|
+
expect(connection_state_change.reason.code).to eq(40142) # Token expired
|
211
211
|
|
212
212
|
# Token has expired, so now ensure it is not used again
|
213
213
|
stub_const 'Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER', original_token_expiry_buffer
|
@@ -333,7 +333,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
333
333
|
expect(expired_token_details).to be_expired
|
334
334
|
connection.once(:connected) { raise 'Connection should never connect as token has expired' }
|
335
335
|
connection.once(:failed) do
|
336
|
-
expect(client.connection.error_reason.code).to eql(
|
336
|
+
expect(client.connection.error_reason.code).to eql(40142)
|
337
337
|
stop_reactor
|
338
338
|
end
|
339
339
|
end
|
@@ -800,6 +800,41 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
800
800
|
end
|
801
801
|
end
|
802
802
|
|
803
|
+
context '#details' do
|
804
|
+
let(:connection) { client.connection }
|
805
|
+
|
806
|
+
it 'is nil before connected' do
|
807
|
+
connection.on(:connecting) do
|
808
|
+
expect(connection.details).to eql(nil)
|
809
|
+
stop_reactor
|
810
|
+
end
|
811
|
+
end
|
812
|
+
|
813
|
+
it 'contains the ConnectionDetails object once connected' do
|
814
|
+
connection.on(:connected) do
|
815
|
+
expect(connection.details).to be_a(Ably::Models::ConnectionDetails)
|
816
|
+
expect(connection.details.connection_key).to_not be_nil
|
817
|
+
expect(connection.details.server_id).to_not be_nil
|
818
|
+
stop_reactor
|
819
|
+
end
|
820
|
+
end
|
821
|
+
|
822
|
+
it 'contains the new ConnectionDetails object once a subsequent connection is created' do
|
823
|
+
connection.once(:connected) do
|
824
|
+
expect(connection.details.connection_key).to_not be_nil
|
825
|
+
old_key = connection.details.connection_key
|
826
|
+
connection.close do
|
827
|
+
connection.once(:connected) do
|
828
|
+
expect(connection.details.connection_key).to_not be_nil
|
829
|
+
expect(connection.details.connection_key).to_not eql(old_key)
|
830
|
+
stop_reactor
|
831
|
+
end
|
832
|
+
connection.connect
|
833
|
+
end
|
834
|
+
end
|
835
|
+
end
|
836
|
+
end
|
837
|
+
|
803
838
|
context 'recovery' do
|
804
839
|
let(:channel_name) { random_str }
|
805
840
|
let(:channel) { client.channel(channel_name) }
|
@@ -813,7 +848,8 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
813
848
|
log_level: :none,
|
814
849
|
disconnected_retry_timeout: 0.1,
|
815
850
|
suspended_retry_timeout: 0.1,
|
816
|
-
connection_state_ttl: 0.2
|
851
|
+
connection_state_ttl: 0.2,
|
852
|
+
realtime_request_timeout: 5
|
817
853
|
)
|
818
854
|
end
|
819
855
|
|
@@ -889,7 +925,8 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
889
925
|
|
890
926
|
context "opening a new connection using a recently disconnected connection's #recovery_key" do
|
891
927
|
context 'connection#id and connection#key after recovery' do
|
892
|
-
it 'remains the same' do
|
928
|
+
it 'remains the same for id and party for key' do
|
929
|
+
connection_key_consistent_part_regex = /.*?!(\w{5,})-/
|
893
930
|
previous_connection_id = nil
|
894
931
|
previous_connection_key = nil
|
895
932
|
|
@@ -902,8 +939,9 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
902
939
|
connection.once(:failed) do
|
903
940
|
recover_client = auto_close Ably::Realtime::Client.new(default_options.merge(recover: client.connection.recovery_key))
|
904
941
|
recover_client.connection.on(:connected) do
|
905
|
-
expect(recover_client.connection.key[
|
906
|
-
expect(recover_client.connection.key[
|
942
|
+
expect(recover_client.connection.key[connection_key_consistent_part_regex, 1]).to_not be_nil
|
943
|
+
expect(recover_client.connection.key[connection_key_consistent_part_regex, 1]).to eql(
|
944
|
+
previous_connection_key[connection_key_consistent_part_regex, 1])
|
907
945
|
expect(recover_client.connection.id).to eql(previous_connection_id)
|
908
946
|
stop_reactor
|
909
947
|
end
|