ably 0.8.12 → 0.8.13
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 -1
- data/README.md +0 -1
- data/ably.gemspec +6 -2
- data/lib/ably/auth.rb +8 -1
- data/lib/ably/realtime/connection.rb +8 -6
- data/lib/ably/rest/client.rb +2 -0
- data/lib/ably/version.rb +3 -1
- data/spec/acceptance/realtime/connection_spec.rb +20 -0
- data/spec/acceptance/realtime/message_spec.rb +132 -10
- data/spec/acceptance/rest/auth_spec.rb +37 -0
- data/spec/acceptance/rest/client_spec.rb +17 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7859d1961b34f4db85c4e3b4dd9148aa17b456e6
|
4
|
+
data.tar.gz: df4339d846d3bb29ce58dc311b7e844d6a21fadb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 711fd1f07710b81c319378740f0b193d0166f16ab00a1528de10c22a105a796212ab77954a7813d631afff1aa82ed7bf1e75f9984a90346b72a636cf5ff74d6d
|
7
|
+
data.tar.gz: 00e82298ba240966faae98bb7d33065bfa58ba118c40152ac906b92f6344f85d951130f23e40947d107dd809f4cd317e9f975b68324babb376a6ad1a36bd0edf
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [
|
3
|
+
## [Unreleased](https://github.com/ably/ably-ruby/tree/v0.8.13)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/ably/ably-ruby/compare/v0.8.12...v0.8.13)
|
6
|
+
|
7
|
+
**Merged pull requests:**
|
8
|
+
|
9
|
+
- Ensure interoperability with other libraries with JSON protocol [\#94](https://github.com/ably/ably-ruby/pull/94) ([mattheworiordan](https://github.com/mattheworiordan))
|
10
|
+
|
11
|
+
## [v0.8.12](https://github.com/ably/ably-ruby/tree/v0.8.12) (2016-05-23)
|
4
12
|
|
5
13
|
[Full Changelog](https://github.com/ably/ably-ruby/compare/v0.8.11...v0.8.12)
|
6
14
|
|
data/README.md
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# [Ably](https://www.ably.io)
|
2
2
|
|
3
|
-
[](https://travis-ci.org/ably/ably-ruby)
|
4
3
|
[](http://badge.fury.io/rb/ably)
|
5
4
|
[](https://coveralls.io/r/ably/ably-ruby)
|
6
5
|
|
data/ably.gemspec
CHANGED
@@ -22,7 +22,11 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_runtime_dependency 'em-http-request', '~> 1.1'
|
23
23
|
spec.add_runtime_dependency 'statesman', '~> 1.0.0'
|
24
24
|
spec.add_runtime_dependency 'faraday', '~> 0.9'
|
25
|
-
|
25
|
+
if RUBY_VERSION.match(/^1/)
|
26
|
+
spec.add_runtime_dependency 'json', '< 2.0'
|
27
|
+
else
|
28
|
+
spec.add_runtime_dependency 'json'
|
29
|
+
end
|
26
30
|
spec.add_runtime_dependency 'websocket-driver', '~> 0.6'
|
27
31
|
spec.add_runtime_dependency 'msgpack', '>= 0.6.2'
|
28
32
|
spec.add_runtime_dependency 'addressable', '>= 2.0.0'
|
@@ -37,7 +41,7 @@ Gem::Specification.new do |spec|
|
|
37
41
|
|
38
42
|
spec.add_development_dependency 'coveralls'
|
39
43
|
|
40
|
-
|
44
|
+
unless RUBY_VERSION.match(/^1/)
|
41
45
|
spec.add_development_dependency 'pry'
|
42
46
|
spec.add_development_dependency 'pry-byebug'
|
43
47
|
end
|
data/lib/ably/auth.rb
CHANGED
@@ -290,7 +290,14 @@ module Ably
|
|
290
290
|
nonce: token_params[:nonce] || SecureRandom.hex.force_encoding('UTF-8')
|
291
291
|
}
|
292
292
|
|
293
|
-
|
293
|
+
if token_request[:capability].is_a?(Hash)
|
294
|
+
lexicographic_ordered_capabilities = Hash[
|
295
|
+
token_request[:capability].sort_by { |key, value| key }.map do |key, value|
|
296
|
+
[key, value.sort]
|
297
|
+
end
|
298
|
+
]
|
299
|
+
token_request[:capability] = JSON.dump(lexicographic_ordered_capabilities)
|
300
|
+
end
|
294
301
|
|
295
302
|
token_request[:mac] = sign_params(token_request, request_key_secret)
|
296
303
|
|
@@ -194,15 +194,15 @@ module Ably
|
|
194
194
|
|
195
195
|
# Sends a ping to Ably and yields the provided block when a heartbeat ping request is echoed from the server.
|
196
196
|
# This can be useful for measuring true roundtrip client to Ably server latency for a simple message, or checking that an underlying transport is responding currently.
|
197
|
-
# The elapsed
|
197
|
+
# The elapsed time in seconds is passed as an argument to the block and represents the time taken to echo a ping heartbeat once the connection is in the `:connected` state.
|
198
198
|
#
|
199
|
-
# @yield [Integer] if a block is passed to this method, then this block will be called once the ping heartbeat is received with the time elapsed in
|
199
|
+
# @yield [Integer] if a block is passed to this method, then this block will be called once the ping heartbeat is received with the time elapsed in seconds.
|
200
200
|
# If the ping is not received within an acceptable timeframe, the block will be called with +nil+ as he first argument
|
201
201
|
#
|
202
202
|
# @example
|
203
203
|
# client = Ably::Rest::Client.new(key: 'key.id:secret')
|
204
|
-
# client.connection.ping do |
|
205
|
-
# puts "Ping took #{
|
204
|
+
# client.connection.ping do |elapsed_s|
|
205
|
+
# puts "Ping took #{elapsed_s}s"
|
206
206
|
# end
|
207
207
|
#
|
208
208
|
# @return [void]
|
@@ -219,7 +219,7 @@ module Ably
|
|
219
219
|
if protocol_message.action == Ably::Models::ProtocolMessage::ACTION.Heartbeat
|
220
220
|
finished = true
|
221
221
|
__incoming_protocol_msgbus__.unsubscribe(:protocol_message, &wait_for_ping)
|
222
|
-
time_passed =
|
222
|
+
time_passed = Time.now.to_f - started.to_f
|
223
223
|
safe_yield block, time_passed if block_given?
|
224
224
|
end
|
225
225
|
end
|
@@ -387,7 +387,9 @@ module Ably
|
|
387
387
|
auth_deferrable.callback do |auth_params|
|
388
388
|
url_params = auth_params.merge(
|
389
389
|
format: client.protocol,
|
390
|
-
echo: client.echo_messages
|
390
|
+
echo: client.echo_messages,
|
391
|
+
v: Ably::PROTOCOL_VERSION,
|
392
|
+
lib: Ably::LIB_VERSION_ID,
|
391
393
|
)
|
392
394
|
|
393
395
|
url_params['clientId'] = client.auth.client_id if client.auth.has_client_id?
|
data/lib/ably/rest/client.rb
CHANGED
@@ -352,6 +352,8 @@ module Ably
|
|
352
352
|
unless options[:send_auth_header] == false
|
353
353
|
request.headers[:authorization] = auth.auth_header
|
354
354
|
end
|
355
|
+
request.headers['X-Ably-Version'] = Ably::PROTOCOL_VERSION
|
356
|
+
request.headers['X-Ably-Lib'] = Ably::LIB_VERSION_ID
|
355
357
|
end
|
356
358
|
|
357
359
|
rescue Faraday::TimeoutError, Faraday::ClientError, Ably::Exceptions::ServerError => error
|
data/lib/ably/version.rb
CHANGED
@@ -1356,5 +1356,25 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
1356
1356
|
end
|
1357
1357
|
end
|
1358
1358
|
end
|
1359
|
+
|
1360
|
+
context 'version params' do
|
1361
|
+
it 'sends the protocol version param v' do
|
1362
|
+
expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
|
1363
|
+
uri = URI.parse(url)
|
1364
|
+
expect(CGI::parse(uri.query)['v'][0]).to eql(Ably::PROTOCOL_VERSION)
|
1365
|
+
stop_reactor
|
1366
|
+
end
|
1367
|
+
client
|
1368
|
+
end
|
1369
|
+
|
1370
|
+
it 'sends the lib version param lib' do
|
1371
|
+
expect(EventMachine).to receive(:connect) do |host, port, transport, object, url|
|
1372
|
+
uri = URI.parse(url)
|
1373
|
+
expect(CGI::parse(uri.query)['lib'][0]).to eql("ruby-#{Ably::VERSION}")
|
1374
|
+
stop_reactor
|
1375
|
+
end
|
1376
|
+
client
|
1377
|
+
end
|
1378
|
+
end
|
1359
1379
|
end
|
1360
1380
|
end
|
@@ -483,11 +483,13 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
483
483
|
payload_description = "#{payload.class}#{" #{payload.encoding}" if payload.kind_of?(String)}"
|
484
484
|
|
485
485
|
it "delivers a #{payload_description} payload to the receiver" do
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
486
|
+
encrypted_channel_client2.attach do
|
487
|
+
encrypted_channel_client1.publish 'example', payload
|
488
|
+
encrypted_channel_client2.subscribe do |message|
|
489
|
+
expect(message.data).to eql(payload)
|
490
|
+
expect(message.encoding).to be_nil
|
491
|
+
stop_reactor
|
492
|
+
end
|
491
493
|
end
|
492
494
|
end
|
493
495
|
end
|
@@ -520,11 +522,13 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
520
522
|
let(:payload) { MessagePack.pack({ 'key' => random_str }) }
|
521
523
|
|
522
524
|
it 'delivers the message but still encrypted with a value in the #encoding attribute' do
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
525
|
+
unencrypted_channel_client2.attach do
|
526
|
+
encrypted_channel_client1.publish 'example', payload
|
527
|
+
unencrypted_channel_client2.subscribe do |message|
|
528
|
+
expect(message.data).to_not eql(payload)
|
529
|
+
expect(message.encoding).to match(/^cipher\+aes-256-cbc/)
|
530
|
+
stop_reactor
|
531
|
+
end
|
528
532
|
end
|
529
533
|
end
|
530
534
|
|
@@ -732,4 +736,122 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
732
736
|
end
|
733
737
|
end
|
734
738
|
end
|
739
|
+
|
740
|
+
context 'message encoding interoperability' do
|
741
|
+
let(:client_options) { { key: api_key, environment: environment, protocol: :json } }
|
742
|
+
let(:channel_name) { "subscribe_send_text-#{random_str}" }
|
743
|
+
|
744
|
+
fixtures_path = File.expand_path('../../../../lib/submodules/ably-common/test-resources/messages-encoding.json', __FILE__)
|
745
|
+
|
746
|
+
context 'over a JSON transport' do
|
747
|
+
let(:realtime_client) do
|
748
|
+
auto_close Ably::Realtime::Client.new(client_options)
|
749
|
+
end
|
750
|
+
let(:rest_client) do
|
751
|
+
Ably::Rest::Client.new(client_options)
|
752
|
+
end
|
753
|
+
let(:realtime_channel) { realtime_client.channels.get(channel_name) }
|
754
|
+
|
755
|
+
JSON.parse(File.read(fixtures_path))['messages'].each do |encoding_spec|
|
756
|
+
context "when decoding #{encoding_spec['expectedType']}" do
|
757
|
+
it 'ensures that client libraries have compatible encoding and decoding using common fixtures' do
|
758
|
+
realtime_channel.attach do
|
759
|
+
realtime_channel.subscribe do |message|
|
760
|
+
if encoding_spec['expectedHexValue']
|
761
|
+
expect(message.data.unpack('H*').first).to eql(encoding_spec['expectedHexValue'])
|
762
|
+
else
|
763
|
+
expect(message.data).to eql(encoding_spec['expectedValue'])
|
764
|
+
end
|
765
|
+
stop_reactor
|
766
|
+
end
|
767
|
+
|
768
|
+
raw_message = { "data" => encoding_spec['data'], "encoding" => encoding_spec['encoding'] }
|
769
|
+
rest_client.post("/channels/#{channel_name}/messages", JSON.dump(raw_message))
|
770
|
+
end
|
771
|
+
end
|
772
|
+
end
|
773
|
+
|
774
|
+
context "when encoding #{encoding_spec['expectedType']}" do
|
775
|
+
it 'ensures that client libraries have compatible encoding and decoding using common fixtures' do
|
776
|
+
data = if encoding_spec['expectedHexValue']
|
777
|
+
encoding_spec['expectedHexValue'].scan(/../).map { |x| x.hex }.pack('c*')
|
778
|
+
else
|
779
|
+
encoding_spec['expectedValue']
|
780
|
+
end
|
781
|
+
|
782
|
+
realtime_channel.publish("event", data) do
|
783
|
+
response = rest_client.get("/channels/#{channel_name}/messages")
|
784
|
+
message = response.body[0]
|
785
|
+
expect(message['encoding']).to eql(encoding_spec['encoding'])
|
786
|
+
if message['encoding'] == 'json'
|
787
|
+
expect(JSON.parse(encoding_spec['data'])).to eql(JSON.parse(message['data']))
|
788
|
+
else
|
789
|
+
expect(encoding_spec['data']).to eql(message['data'])
|
790
|
+
end
|
791
|
+
stop_reactor
|
792
|
+
end
|
793
|
+
end
|
794
|
+
end
|
795
|
+
end
|
796
|
+
end
|
797
|
+
|
798
|
+
context 'over a MsgPack transport' do
|
799
|
+
JSON.parse(File.read(fixtures_path))['messages'].each do |encoding_spec|
|
800
|
+
context "when publishing a #{encoding_spec['expectedType']} using JSON protocol" do
|
801
|
+
let(:rest_publish_client) do
|
802
|
+
Ably::Rest::Client.new(client_options.merge(protocol: :json))
|
803
|
+
end
|
804
|
+
let(:realtime_subscribe_client) do
|
805
|
+
Ably::Realtime::Client.new(client_options.merge(protocol: :msgpack))
|
806
|
+
end
|
807
|
+
let(:realtime_subscribe_channel) { realtime_subscribe_client.channels.get(channel_name) }
|
808
|
+
|
809
|
+
it 'receives the message over MsgPack and the data matches' do
|
810
|
+
expect(realtime_subscribe_client).to be_protocol_binary
|
811
|
+
|
812
|
+
realtime_subscribe_channel.attach do
|
813
|
+
realtime_subscribe_channel.subscribe do |message|
|
814
|
+
if encoding_spec['expectedHexValue']
|
815
|
+
expect(message.data.unpack('H*').first).to eql(encoding_spec['expectedHexValue'])
|
816
|
+
else
|
817
|
+
expect(message.data).to eql(encoding_spec['expectedValue'])
|
818
|
+
end
|
819
|
+
stop_reactor
|
820
|
+
end
|
821
|
+
|
822
|
+
raw_message = { "data" => encoding_spec['data'], "encoding" => encoding_spec['encoding'] }
|
823
|
+
rest_publish_client.post("/channels/#{channel_name}/messages", JSON.dump(raw_message))
|
824
|
+
end
|
825
|
+
end
|
826
|
+
end
|
827
|
+
|
828
|
+
context "when retrieving a #{encoding_spec['expectedType']} using JSON protocol" do
|
829
|
+
let(:rest_publish_client) do
|
830
|
+
Ably::Rest::Client.new(client_options.merge(protocol: :msgpack))
|
831
|
+
end
|
832
|
+
let(:rest_retrieve_client) do
|
833
|
+
Ably::Rest::Client.new(client_options.merge(protocol: :json))
|
834
|
+
end
|
835
|
+
let(:rest_publish_channel) { rest_publish_client.channels.get(channel_name) }
|
836
|
+
|
837
|
+
it 'is compatible with a publishes using MsgPack' do
|
838
|
+
expect(rest_publish_client).to be_protocol_binary
|
839
|
+
|
840
|
+
data = if encoding_spec['expectedHexValue']
|
841
|
+
encoding_spec['expectedHexValue'].scan(/../).map { |x| x.hex }.pack('c*')
|
842
|
+
else
|
843
|
+
encoding_spec['expectedValue']
|
844
|
+
end
|
845
|
+
rest_publish_channel.publish "event", data
|
846
|
+
|
847
|
+
response = rest_retrieve_client.get("/channels/#{channel_name}/messages")
|
848
|
+
message = response.body[0]
|
849
|
+
expect(message['encoding']).to eql(encoding_spec['encoding'])
|
850
|
+
expect(encoding_spec['data']).to eql(message['data'])
|
851
|
+
stop_reactor
|
852
|
+
end
|
853
|
+
end
|
854
|
+
end
|
855
|
+
end
|
856
|
+
end
|
735
857
|
end
|
@@ -974,6 +974,43 @@ describe Ably::Auth do
|
|
974
974
|
hmac = hmac_for(Ably::Models::TokenRequest(token_request_attributes).attributes, key_secret)
|
975
975
|
expect(subject['mac']).to eql(hmac)
|
976
976
|
end
|
977
|
+
|
978
|
+
context 'lexicographic ordering of channels and operations' do
|
979
|
+
let(:token_attributes) do
|
980
|
+
{
|
981
|
+
key_name: key_name,
|
982
|
+
ttl: 600,
|
983
|
+
capability: {
|
984
|
+
"channel2" => ["subscribe", "publish"],
|
985
|
+
"channel1" => ["subscribe", "history"]
|
986
|
+
},
|
987
|
+
client_id: random_str,
|
988
|
+
nonce: random_str,
|
989
|
+
timestamp: Time.now.to_i
|
990
|
+
}
|
991
|
+
end
|
992
|
+
|
993
|
+
let(:token_attributes_ordered) do
|
994
|
+
token_attributes.merge(capability: {
|
995
|
+
"channel1" => ["history", "subscribe"],
|
996
|
+
"channel2" => ["publish", "subscribe"]
|
997
|
+
})
|
998
|
+
end
|
999
|
+
|
1000
|
+
specify 'HMAC is lexicographic ordered and thus the HMAC is identical' do
|
1001
|
+
hmac = auth.create_token_request(token_attributes).mac
|
1002
|
+
hmac_ordered = auth.create_token_request(token_attributes_ordered).mac
|
1003
|
+
expect(hmac).to eql(hmac_ordered)
|
1004
|
+
end
|
1005
|
+
|
1006
|
+
it 'is valid when used for authentication' do
|
1007
|
+
auth_callback = Proc.new do
|
1008
|
+
auth.create_token_request(token_attributes)
|
1009
|
+
end
|
1010
|
+
client = Ably::Rest::Client.new(auth_callback: auth_callback, environment: environment, protocol: protocol)
|
1011
|
+
client.auth.authorise
|
1012
|
+
end
|
1013
|
+
end
|
977
1014
|
end
|
978
1015
|
end
|
979
1016
|
|
@@ -545,5 +545,22 @@ describe Ably::Rest::Client do
|
|
545
545
|
expect(client.auth.options[:auth_url]).to eql(dummy_auth_url)
|
546
546
|
end
|
547
547
|
end
|
548
|
+
|
549
|
+
context 'version headers', :webmock do
|
550
|
+
let(:client_options) { default_options.merge(key: api_key) }
|
551
|
+
let!(:publish_message_stub) do
|
552
|
+
stub_request(:post, "#{client.endpoint.to_s.gsub('://', "://#{api_key}@")}/channels/foo/publish").
|
553
|
+
with(headers: {
|
554
|
+
'X-Ably-Version' => Ably::PROTOCOL_VERSION,
|
555
|
+
'X-Ably-Lib' => "ruby-#{Ably::VERSION}"
|
556
|
+
}).
|
557
|
+
to_return(status: 201, body: '{}', headers: { 'Content-Type' => 'application/json' })
|
558
|
+
end
|
559
|
+
|
560
|
+
it 'sends a protocol version and lib version header' do
|
561
|
+
client.channels.get('foo').publish("event")
|
562
|
+
expect(publish_message_stub).to have_been_requested
|
563
|
+
end
|
564
|
+
end
|
548
565
|
end
|
549
566
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ably
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lewis Marshall
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-09-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|