ably 0.8.12 → 0.8.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Build Status](https://travis-ci.org/ably/ably-ruby.png)](https://travis-ci.org/ably/ably-ruby)
|
4
3
|
[![Gem Version](https://badge.fury.io/rb/ably.svg)](http://badge.fury.io/rb/ably)
|
5
4
|
[![Coverage Status](https://coveralls.io/repos/ably/ably-ruby/badge.svg)](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
|