ably 1.1.4 → 1.1.5
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/SPEC.md +289 -221
- data/ably.gemspec +2 -2
- data/lib/ably/modules/ably.rb +11 -1
- data/lib/ably/realtime/client.rb +1 -0
- data/lib/ably/rest/client.rb +13 -6
- data/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +4 -1
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/connection_failures_spec.rb +26 -11
- data/spec/acceptance/realtime/connection_spec.rb +8 -5
- data/spec/acceptance/rest/base_spec.rb +8 -4
- data/spec/acceptance/rest/client_spec.rb +49 -14
- data/spec/shared/client_initializer_behaviour.rb +131 -0
- metadata +9 -15
data/ably.gemspec
CHANGED
@@ -21,8 +21,8 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_runtime_dependency 'eventmachine', '~> 1.2.6'
|
22
22
|
spec.add_runtime_dependency 'em-http-request', '~> 1.1'
|
23
23
|
spec.add_runtime_dependency 'statesman', '~> 7.4'
|
24
|
-
spec.add_runtime_dependency 'faraday', '
|
25
|
-
spec.add_runtime_dependency '
|
24
|
+
spec.add_runtime_dependency 'faraday', '~> 1.0'
|
25
|
+
spec.add_runtime_dependency 'typhoeus', '~> 1.4'
|
26
26
|
|
27
27
|
if RUBY_VERSION.match(/^1\./)
|
28
28
|
spec.add_runtime_dependency 'json', '< 2.0'
|
data/lib/ably/modules/ably.rb
CHANGED
@@ -6,8 +6,18 @@
|
|
6
6
|
module Ably
|
7
7
|
# Fallback hosts to use when a connection to rest/realtime.ably.io is not possible due to
|
8
8
|
# network failures either at the client, between the client and Ably, within an Ably data center, or at the IO domain registrar
|
9
|
+
# see https://docs.ably.io/client-lib-development-guide/features/#RSC15a
|
9
10
|
#
|
10
|
-
|
11
|
+
FALLBACK_DOMAIN = 'ably-realtime.com'.freeze
|
12
|
+
FALLBACK_IDS = %w(a b c d e).freeze
|
13
|
+
|
14
|
+
# Default production fallbacks a.ably-realtime.com ... e.ably-realtime.com
|
15
|
+
FALLBACK_HOSTS = FALLBACK_IDS.map { |host| "#{host}.#{FALLBACK_DOMAIN}".freeze }.freeze
|
16
|
+
|
17
|
+
# Custom environment default fallbacks {ENV}-a-fallback.ably-realtime.com ... {ENV}-a-fallback.ably-realtime.com
|
18
|
+
CUSTOM_ENVIRONMENT_FALLBACKS_SUFFIXES = FALLBACK_IDS.map do |host|
|
19
|
+
"-#{host}-fallback.#{FALLBACK_DOMAIN}".freeze
|
20
|
+
end.freeze
|
11
21
|
|
12
22
|
INTERNET_CHECK = {
|
13
23
|
url: '//internet-up.ably-realtime.com/is-the-internet-up.txt',
|
data/lib/ably/realtime/client.rb
CHANGED
@@ -74,6 +74,7 @@ module Ably
|
|
74
74
|
def_delegators :@rest_client, :use_tls?, :protocol, :protocol_binary?
|
75
75
|
def_delegators :@rest_client, :environment, :custom_host, :custom_port, :custom_tls_port
|
76
76
|
def_delegators :@rest_client, :log_level
|
77
|
+
def_delegators :@rest_client, :options
|
77
78
|
|
78
79
|
# Creates a {Ably::Realtime::Client Realtime Client} and configures the {Ably::Auth} object for the connection.
|
79
80
|
#
|
data/lib/ably/rest/client.rb
CHANGED
@@ -3,6 +3,9 @@ require 'json'
|
|
3
3
|
require 'logger'
|
4
4
|
require 'uri'
|
5
5
|
|
6
|
+
require 'typhoeus'
|
7
|
+
require 'typhoeus/adapters/faraday'
|
8
|
+
|
6
9
|
require 'ably/rest/middleware/exceptions'
|
7
10
|
|
8
11
|
module Ably
|
@@ -181,16 +184,18 @@ module Ably
|
|
181
184
|
@idempotent_rest_publishing = options.delete(:idempotent_rest_publishing) || Ably.major_minor_version_numeric > 1.1
|
182
185
|
|
183
186
|
|
184
|
-
if options[:fallback_hosts_use_default] && options[:
|
185
|
-
raise ArgumentError, "fallback_hosts_use_default cannot be set to
|
187
|
+
if options[:fallback_hosts_use_default] && options[:fallback_hosts]
|
188
|
+
raise ArgumentError, "fallback_hosts_use_default cannot be set to try when fallback_hosts is also provided"
|
186
189
|
end
|
187
190
|
@fallback_hosts = case
|
188
191
|
when options.delete(:fallback_hosts_use_default)
|
189
192
|
Ably::FALLBACK_HOSTS
|
190
193
|
when options_fallback_hosts = options.delete(:fallback_hosts)
|
191
194
|
options_fallback_hosts
|
192
|
-
when
|
195
|
+
when custom_host || options[:realtime_host] || custom_port || custom_tls_port
|
193
196
|
[]
|
197
|
+
when environment
|
198
|
+
CUSTOM_ENVIRONMENT_FALLBACKS_SUFFIXES.map { |host| "#{environment}#{host}" }
|
194
199
|
else
|
195
200
|
Ably::FALLBACK_HOSTS
|
196
201
|
end
|
@@ -202,6 +207,8 @@ module Ably
|
|
202
207
|
@http_defaults = HTTP_DEFAULTS.dup
|
203
208
|
options.each do |key, val|
|
204
209
|
if http_key = key[/^http_(.+)/, 1]
|
210
|
+
# Typhoeus converts decimal durations to milliseconds, so 0.0001 timeout is treated as 0 (no timeout)
|
211
|
+
val = 0.001 if val.kind_of?(Numeric) && (val > 0) && (val < 0.001)
|
205
212
|
@http_defaults[http_key.to_sym] = val if val && @http_defaults.has_key?(http_key.to_sym)
|
206
213
|
end
|
207
214
|
end
|
@@ -665,7 +672,7 @@ module Ably
|
|
665
672
|
}
|
666
673
|
end
|
667
674
|
|
668
|
-
# Return a Faraday middleware stack to initiate the Faraday::
|
675
|
+
# Return a Faraday middleware stack to initiate the Faraday::RackBuilder with
|
669
676
|
#
|
670
677
|
# @see http://mislav.uniqpath.com/2011/07/faraday-advanced-http/
|
671
678
|
def middleware
|
@@ -677,8 +684,8 @@ module Ably
|
|
677
684
|
|
678
685
|
setup_incoming_middleware builder, logger, fail_if_unsupported_mime_type: true
|
679
686
|
|
680
|
-
# Set Faraday's HTTP adapter
|
681
|
-
builder.adapter :
|
687
|
+
# Set Faraday's HTTP adapter with support for HTTP/2
|
688
|
+
builder.adapter :typhoeus, http_version: :httpv2_0
|
682
689
|
end
|
683
690
|
end
|
684
691
|
|
@@ -7,7 +7,10 @@ module Ably
|
|
7
7
|
class FailIfUnsupportedMimeType < Faraday::Response::Middleware
|
8
8
|
def on_complete(env)
|
9
9
|
unless env.response_headers['Ably-Middleware-Parsed'] == true
|
10
|
-
|
10
|
+
# Ignore empty body with success status code for no body response
|
11
|
+
return if env.body.to_s.empty? && env.status == 204
|
12
|
+
|
13
|
+
unless (500..599).include?(env.status)
|
11
14
|
raise Ably::Exceptions::InvalidResponseBody,
|
12
15
|
"Content Type #{env.response_headers['Content-Type']} is not supported by this client library"
|
13
16
|
end
|
data/lib/ably/version.rb
CHANGED
@@ -156,10 +156,20 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
156
156
|
|
157
157
|
stub_request(:get, auth_url).
|
158
158
|
to_return do |request|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
159
|
+
sleep Ably::Rest::Client::HTTP_DEFAULTS.fetch(:request_timeout)
|
160
|
+
{ status: [500, "Internal Server Error"] }
|
161
|
+
end.then.
|
162
|
+
to_return(:status => 201, :body => token_response.to_json, :headers => { 'Content-Type' => 'application/json' })
|
163
|
+
|
164
|
+
stub_request(:get, 'https://internet-up.ably-realtime.com/is-the-internet-up.txt')
|
165
|
+
.with(
|
166
|
+
headers: {
|
167
|
+
'Accept-Encoding' => 'gzip, compressed',
|
168
|
+
'Connection' => 'close',
|
169
|
+
'Host' => 'internet-up.ably-realtime.com',
|
170
|
+
'User-Agent' => 'EventMachine HttpClient'
|
171
|
+
}
|
172
|
+
).to_return(status: 200, body: 'yes\n', headers: { 'Content-Type' => 'text/plain' })
|
163
173
|
end
|
164
174
|
|
165
175
|
specify 'the connection moves to the disconnected state and tries again, returning again to the disconnected state (#RSA4c, #RSA4c1, #RSA4c2)' do
|
@@ -1423,14 +1433,19 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
1423
1433
|
let(:expected_host) { "#{environment}-#{Ably::Realtime::Client::DOMAIN}" }
|
1424
1434
|
let(:client_options) { timeout_options.merge(environment: environment) }
|
1425
1435
|
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1436
|
+
context ':fallback_hosts_use_default is unset' do
|
1437
|
+
let(:max_time_in_state_for_tests) { 8 }
|
1438
|
+
let(:expected_hosts) { Ably::CUSTOM_ENVIRONMENT_FALLBACKS_SUFFIXES.map { |suffix| "#{environment}#{suffix}" } + [expected_host] }
|
1439
|
+
let(:fallback_hosts_used) { Array.new }
|
1440
|
+
|
1441
|
+
it 'uses fallback hosts by default' do
|
1442
|
+
allow(connection).to receive(:create_transport) do |host|
|
1443
|
+
fallback_hosts_used << host
|
1444
|
+
raise EventMachine::ConnectionError
|
1445
|
+
end
|
1431
1446
|
|
1432
|
-
connection.once(:suspended) do
|
1433
1447
|
connection.once(:suspended) do
|
1448
|
+
expect(fallback_hosts_used.uniq).to match_array(expected_hosts)
|
1434
1449
|
stop_reactor
|
1435
1450
|
end
|
1436
1451
|
end
|
@@ -1508,7 +1523,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
1508
1523
|
end
|
1509
1524
|
|
1510
1525
|
context 'with production environment' do
|
1511
|
-
let(:custom_hosts) { %w(
|
1526
|
+
let(:custom_hosts) { %w(a.ably-realtime.com b.ably-realtime.com) }
|
1512
1527
|
before do
|
1513
1528
|
stub_const 'Ably::FALLBACK_HOSTS', custom_hosts
|
1514
1529
|
end
|
@@ -122,7 +122,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
|
-
context 'with immediately expired token' do
|
125
|
+
context 'with immediately expired token and no fallback hosts' do
|
126
126
|
let(:ttl) { 0.001 }
|
127
127
|
let(:auth_requests) { [] }
|
128
128
|
let(:token_callback) do
|
@@ -131,7 +131,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
131
131
|
Ably::Rest::Client.new(default_options).auth.request_token(ttl: ttl).token
|
132
132
|
end
|
133
133
|
end
|
134
|
-
let(:client_options) { default_options.merge(auth_callback: token_callback) }
|
134
|
+
let(:client_options) { default_options.merge(auth_callback: token_callback, fallback_hosts: []) }
|
135
135
|
|
136
136
|
it 'renews the token on connect, and makes one immediate subsequent attempt to obtain a new token (#RSA4b)' do
|
137
137
|
started_at = Time.now.to_f
|
@@ -146,7 +146,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
146
146
|
end
|
147
147
|
|
148
148
|
context 'when disconnected_retry_timeout is 0.5 seconds' do
|
149
|
-
let(:client_options) { default_options.merge(disconnected_retry_timeout: 0.5, auth_callback: token_callback) }
|
149
|
+
let(:client_options) { default_options.merge(disconnected_retry_timeout: 0.5, auth_callback: token_callback, fallback_hosts: []) }
|
150
150
|
|
151
151
|
it 'renews the token on connect, and continues to attempt renew based on the retry schedule' do
|
152
152
|
disconnect_count = 0
|
@@ -172,7 +172,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
172
172
|
end
|
173
173
|
|
174
174
|
context 'using implicit token auth' do
|
175
|
-
let(:client_options) { default_options.merge(use_token_auth: true, default_token_params: { ttl: ttl }) }
|
175
|
+
let(:client_options) { default_options.merge(use_token_auth: true, default_token_params: { ttl: ttl }, fallback_hosts: []) }
|
176
176
|
|
177
177
|
before do
|
178
178
|
stub_const 'Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER', -10 # ensure client lib thinks token is still valid
|
@@ -441,7 +441,9 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
441
441
|
end
|
442
442
|
end
|
443
443
|
|
444
|
-
context '#connect' do
|
444
|
+
context '#connect with no fallbacks' do
|
445
|
+
let(:client_options) { default_options.merge(fallback_hosts: []) }
|
446
|
+
|
445
447
|
it 'returns a SafeDeferrable that catches exceptions in callbacks and logs them' do
|
446
448
|
expect(connection.connect).to be_a(Ably::Util::SafeDeferrable)
|
447
449
|
stop_reactor
|
@@ -1167,6 +1169,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
1167
1169
|
host: 'this.host.does.not.exist.com'
|
1168
1170
|
)
|
1169
1171
|
)
|
1172
|
+
allow(client).to receive(:fallback_hosts).and_return([])
|
1170
1173
|
|
1171
1174
|
connection.transition_state_machine! :disconnected
|
1172
1175
|
end
|
@@ -87,8 +87,10 @@ describe Ably::Rest do
|
|
87
87
|
let(:error_response) { '{ "error": { "statusCode": 500, "code": 50000, "message": "Internal error" } }' }
|
88
88
|
|
89
89
|
before do
|
90
|
-
|
91
|
-
|
90
|
+
(client.fallback_hosts.map { |host| "https://#{host}" } + [client.endpoint]).each do |host|
|
91
|
+
stub_request(:get, "#{host}/time")
|
92
|
+
.to_return(:status => 500, :body => error_response, :headers => { 'Content-Type' => 'application/json' })
|
93
|
+
end
|
92
94
|
end
|
93
95
|
|
94
96
|
it 'should raise a ServerError exception' do
|
@@ -98,8 +100,10 @@ describe Ably::Rest do
|
|
98
100
|
|
99
101
|
describe '500 server error without a valid JSON response body', :webmock do
|
100
102
|
before do
|
101
|
-
|
102
|
-
|
103
|
+
(client.fallback_hosts.map { |host| "https://#{host}" } + [client.endpoint]).each do |host|
|
104
|
+
stub_request(:get, "#{host}/time").
|
105
|
+
to_return(:status => 500, :headers => { 'Content-Type' => 'application/json' })
|
106
|
+
end
|
103
107
|
end
|
104
108
|
|
105
109
|
it 'should raise a ServerError exception' do
|
@@ -301,30 +301,44 @@ describe Ably::Rest::Client do
|
|
301
301
|
context 'configured' do
|
302
302
|
let(:client_options) { default_options.merge(key: api_key, environment: 'production') }
|
303
303
|
|
304
|
-
it 'should make connection attempts to
|
304
|
+
it 'should make connection attempts to a.ably-realtime.com, b.ably-realtime.com, c.ably-realtime.com, d.ably-realtime.com, e.ably-realtime.com (#RSC15a)' do
|
305
305
|
hosts = []
|
306
306
|
5.times do
|
307
307
|
hosts << client.fallback_connection.host
|
308
308
|
end
|
309
|
-
expect(hosts).to match_array(%w(
|
309
|
+
expect(hosts).to match_array(%w(a.ably-realtime.com b.ably-realtime.com c.ably-realtime.com d.ably-realtime.com e.ably-realtime.com))
|
310
310
|
end
|
311
311
|
end
|
312
312
|
|
313
313
|
context 'when environment is NOT production (#RSC15b)' do
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
314
|
+
context 'and custom fallback hosts are empty' do
|
315
|
+
let(:client_options) { default_options.merge(environment: 'sandbox', key: api_key, fallback_hosts: []) }
|
316
|
+
let!(:default_host_request_stub) do
|
317
|
+
stub_request(:post, "https://#{environment}-#{Ably::Rest::Client::DOMAIN}#{path}").to_return do
|
318
|
+
raise Faraday::TimeoutError.new('timeout error message')
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
it 'does not retry failed requests with fallback hosts when there is a connection error' do
|
323
|
+
expect { publish_block.call }.to raise_error Ably::Exceptions::ConnectionTimeout
|
318
324
|
end
|
319
325
|
end
|
320
326
|
|
321
|
-
|
322
|
-
|
327
|
+
context 'and no custom fallback hosts are provided' do
|
328
|
+
let(:client_options) { default_options.merge(environment: 'sandbox', key: api_key) }
|
329
|
+
|
330
|
+
it 'should make connection attempts to sandbox-a-fallback.ably-realtime.com, sandbox-b-fallback.ably-realtime.com, sandbox-c-fallback.ably-realtime.com, sandbox-d-fallback.ably-realtime.com, sandbox-e-fallback.ably-realtime.com (#RSC15a)' do
|
331
|
+
hosts = []
|
332
|
+
5.times do
|
333
|
+
hosts << client.fallback_connection.host
|
334
|
+
end
|
335
|
+
expect(hosts).to match_array(%w(a b c d e).map { |id| "sandbox-#{id}-fallback.ably-realtime.com" })
|
336
|
+
end
|
323
337
|
end
|
324
338
|
end
|
325
339
|
|
326
340
|
context 'when environment is production' do
|
327
|
-
let(:custom_hosts) { %w(
|
341
|
+
let(:custom_hosts) { %w(a.ably-realtime.com b.ably-realtime.com) }
|
328
342
|
let(:max_retry_count) { 2 }
|
329
343
|
let(:max_retry_duration) { 0.5 }
|
330
344
|
let(:fallback_block) { proc { raise Faraday::SSLError.new('ssl error message') } }
|
@@ -823,11 +837,12 @@ describe Ably::Rest::Client do
|
|
823
837
|
end
|
824
838
|
|
825
839
|
context 'when environment is not production and server returns a 50x error' do
|
840
|
+
let(:env) { 'custom-env' }
|
841
|
+
let(:default_fallbacks) { %w(a b c d e).map { |id| "#{env}-#{id}-fallback.ably-realtime.com" } }
|
826
842
|
let(:custom_hosts) { %w(A.foo.com B.foo.com) }
|
827
843
|
let(:max_retry_count) { 2 }
|
828
844
|
let(:max_retry_duration) { 0.5 }
|
829
845
|
let(:fallback_block) { proc { raise Faraday::SSLError.new('ssl error message') } }
|
830
|
-
let(:env) { 'custom-env' }
|
831
846
|
let(:production_options) do
|
832
847
|
default_options.merge(
|
833
848
|
environment: env,
|
@@ -851,6 +866,26 @@ describe Ably::Rest::Client do
|
|
851
866
|
stub_request(:post, "https://#{env}-#{Ably::Rest::Client::DOMAIN}#{path}").to_return(&fallback_block)
|
852
867
|
end
|
853
868
|
|
869
|
+
context 'with no fallback hosts provided (#TBC, see https://github.com/ably/wiki/issues/361)' do
|
870
|
+
let(:client_options) {
|
871
|
+
production_options.merge(log_level: :fatal)
|
872
|
+
}
|
873
|
+
|
874
|
+
it 'uses the default fallback hosts for that environment as this is not an authentication failure' do
|
875
|
+
fallbacks_called_count = 0
|
876
|
+
default_fallbacks.each do |host|
|
877
|
+
counting_fallback_proc = proc do
|
878
|
+
fallbacks_called_count += 1
|
879
|
+
fallback_block.call
|
880
|
+
end
|
881
|
+
stub_request(:post, "https://#{host}#{path}").to_return(&counting_fallback_proc)
|
882
|
+
end
|
883
|
+
expect { publish_block.call }.to raise_error(Ably::Exceptions::ServerError)
|
884
|
+
expect(default_host_request_stub).to have_been_requested
|
885
|
+
expect(fallbacks_called_count).to be >= 2
|
886
|
+
end
|
887
|
+
end
|
888
|
+
|
854
889
|
context 'with custom fallback hosts provided (#RSC15b, #TO3k6)' do
|
855
890
|
let!(:first_fallback_request_stub) do
|
856
891
|
stub_request(:post, "https://#{custom_hosts[0]}#{path}").to_return(&fallback_block)
|
@@ -1194,9 +1229,9 @@ describe Ably::Rest::Client do
|
|
1194
1229
|
|
1195
1230
|
context 'request_id generation' do
|
1196
1231
|
context 'Timeout error' do
|
1197
|
-
context 'with option add_request_ids: true', :webmock, :prevent_log_stubbing do
|
1232
|
+
context 'with option add_request_ids: true and no fallback hosts', :webmock, :prevent_log_stubbing do
|
1198
1233
|
let(:custom_logger_object) { TestLogger.new }
|
1199
|
-
let(:client_options) { default_options.merge(key: api_key, logger: custom_logger_object, add_request_ids: true) }
|
1234
|
+
let(:client_options) { default_options.merge(key: api_key, logger: custom_logger_object, add_request_ids: true, fallback_hosts: []) }
|
1200
1235
|
|
1201
1236
|
before do
|
1202
1237
|
@request_id = nil
|
@@ -1286,8 +1321,8 @@ describe Ably::Rest::Client do
|
|
1286
1321
|
end
|
1287
1322
|
end
|
1288
1323
|
|
1289
|
-
context 'without request_id' do
|
1290
|
-
let(:client_options) { default_options.merge(key: api_key, http_request_timeout: 0) }
|
1324
|
+
context 'without request_id and no fallback hosts' do
|
1325
|
+
let(:client_options) { default_options.merge(key: api_key, http_request_timeout: 0, fallback_hosts: []) }
|
1291
1326
|
|
1292
1327
|
it 'does not include request_id in ConnectionTimeout error' do
|
1293
1328
|
begin
|
@@ -265,6 +265,137 @@ shared_examples 'a client initializer' do
|
|
265
265
|
end
|
266
266
|
end
|
267
267
|
end
|
268
|
+
|
269
|
+
context 'environment' do
|
270
|
+
context 'when set without custom fallback hosts configured' do
|
271
|
+
let(:environment) { 'foo' }
|
272
|
+
let(:client_options) { default_options.merge(environment: environment) }
|
273
|
+
let(:default_fallbacks) { %w(a b c d e).map { |id| "#{environment}-#{id}-fallback.ably-realtime.com" } }
|
274
|
+
|
275
|
+
it 'sets the environment attribute' do
|
276
|
+
expect(subject.environment).to eql(environment)
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'uses the default fallback hosts (#TBC, see https://github.com/ably/wiki/issues/361)' do
|
280
|
+
expect(subject.fallback_hosts.sort).to eql(default_fallbacks)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
context 'when set with custom fallback hosts configured' do
|
285
|
+
let(:environment) { 'foo' }
|
286
|
+
let(:custom_fallbacks) { %w(a b c).map { |id| "#{environment}-#{id}.foo.com" } }
|
287
|
+
let(:client_options) { default_options.merge(environment: environment, fallback_hosts: custom_fallbacks) }
|
288
|
+
|
289
|
+
it 'sets the environment attribute' do
|
290
|
+
expect(subject.environment).to eql(environment)
|
291
|
+
end
|
292
|
+
|
293
|
+
it 'uses the custom provided fallback hosts (#RSC15a)' do
|
294
|
+
expect(subject.fallback_hosts.sort).to eql(custom_fallbacks)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
context 'when set with fallback_hosts_use_default' do
|
299
|
+
let(:environment) { 'foo' }
|
300
|
+
let(:custom_fallbacks) { %w(a b c).map { |id| "#{environment}-#{id}.foo.com" } }
|
301
|
+
let(:default_production_fallbacks) { %w(a b c d e).map { |id| "#{id}.ably-realtime.com" } }
|
302
|
+
let(:client_options) { default_options.merge(environment: environment, fallback_hosts_use_default: true) }
|
303
|
+
|
304
|
+
it 'sets the environment attribute' do
|
305
|
+
expect(subject.environment).to eql(environment)
|
306
|
+
end
|
307
|
+
|
308
|
+
it 'uses the production default fallback hosts (#RTN17b)' do
|
309
|
+
expect(subject.fallback_hosts.sort).to eql(default_production_fallbacks)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
context 'rest_host' do
|
315
|
+
context 'when set without custom fallback hosts configured' do
|
316
|
+
let(:custom_rest_host) { 'foo.com' }
|
317
|
+
let(:client_options) { default_options.merge(rest_host: custom_rest_host) }
|
318
|
+
|
319
|
+
it 'sets the custom_host attribute' do
|
320
|
+
expect(subject.custom_host).to eql(custom_rest_host)
|
321
|
+
end
|
322
|
+
|
323
|
+
it 'has no default fallback hosts' do
|
324
|
+
expect(subject.fallback_hosts).to be_empty
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
context 'when set with environment and without custom fallback hosts configured' do
|
329
|
+
let(:environment) { 'foobar' }
|
330
|
+
let(:custom_rest_host) { 'foo.com' }
|
331
|
+
let(:client_options) { default_options.merge(environment: environment, rest_host: custom_rest_host) }
|
332
|
+
|
333
|
+
it 'sets the environment attribute' do
|
334
|
+
expect(subject.environment).to eql(environment)
|
335
|
+
end
|
336
|
+
|
337
|
+
it 'sets the custom_host attribute' do
|
338
|
+
expect(subject.custom_host).to eql(custom_rest_host)
|
339
|
+
end
|
340
|
+
|
341
|
+
it 'has no default fallback hosts' do
|
342
|
+
expect(subject.fallback_hosts).to be_empty
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
context 'when set with custom fallback hosts configured' do
|
347
|
+
let(:custom_rest_host) { 'foo.com' }
|
348
|
+
let(:custom_fallbacks) { %w(a b c).map { |id| "#{environment}-#{id}.foo.com" } }
|
349
|
+
let(:client_options) { default_options.merge(rest_host: custom_rest_host, fallback_hosts: custom_fallbacks) }
|
350
|
+
|
351
|
+
it 'sets the custom_host attribute' do
|
352
|
+
expect(subject.custom_host).to eql(custom_rest_host)
|
353
|
+
end
|
354
|
+
|
355
|
+
it 'has no default fallback hosts' do
|
356
|
+
expect(subject.fallback_hosts.sort).to eql(custom_fallbacks)
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
context 'realtime_host' do
|
362
|
+
context 'when set without custom fallback hosts configured' do
|
363
|
+
let(:custom_realtime_host) { 'realtime.foo.com' }
|
364
|
+
let(:client_options) { default_options.merge(realtime_host: custom_realtime_host) }
|
365
|
+
|
366
|
+
# These tests are shared between realtime & rest clients
|
367
|
+
# So don't test for the attribute, instead test the options
|
368
|
+
it 'sets the realtime_host option' do
|
369
|
+
expect(subject.options[:realtime_host]).to eql(custom_realtime_host)
|
370
|
+
end
|
371
|
+
|
372
|
+
it 'has no default fallback hosts' do
|
373
|
+
expect(subject.fallback_hosts).to be_empty
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
context 'custom port' do
|
379
|
+
context 'when set without custom fallback hosts configured' do
|
380
|
+
let(:custom_port) { 555 }
|
381
|
+
let(:client_options) { default_options.merge(port: custom_port) }
|
382
|
+
|
383
|
+
it 'has no default fallback hosts' do
|
384
|
+
expect(subject.fallback_hosts).to be_empty
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
context 'custom TLS port' do
|
390
|
+
context 'when set without custom fallback hosts configured' do
|
391
|
+
let(:custom_port) { 555 }
|
392
|
+
let(:client_options) { default_options.merge(tls_port: custom_port) }
|
393
|
+
|
394
|
+
it 'has no default fallback hosts' do
|
395
|
+
expect(subject.fallback_hosts).to be_empty
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
268
399
|
end
|
269
400
|
|
270
401
|
context 'delegators' do
|