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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 83a334452c78f5a9522b8aef6edef8a376da22c4
4
- data.tar.gz: e00a360302db7a510633beeb840c1a81d565d3f8
3
+ metadata.gz: 7859d1961b34f4db85c4e3b4dd9148aa17b456e6
4
+ data.tar.gz: df4339d846d3bb29ce58dc311b7e844d6a21fadb
5
5
  SHA512:
6
- metadata.gz: 46211a7336813fdcbc6160b161c97a7a66af8cc95ad02b40757d55326f30839a9754db67c95235a394805d1cea7afe52618311556c55436127f99f92349a26e0
7
- data.tar.gz: 67674b15c02b127e72d0b982b40735f1366b6b0384e8e0cbe0945334e6c724fd2e1c162dac12c99d9c8a12a8d19fa78685749036da4ab3ac972ba9e3274890d8
6
+ metadata.gz: 711fd1f07710b81c319378740f0b193d0166f16ab00a1528de10c22a105a796212ab77954a7813d631afff1aa82ed7bf1e75f9984a90346b72a636cf5ff74d6d
7
+ data.tar.gz: 00e82298ba240966faae98bb7d33065bfa58ba118c40152ac906b92f6344f85d951130f23e40947d107dd809f4cd317e9f975b68324babb376a6ad1a36bd0edf
@@ -1,6 +1,14 @@
1
1
  # Change Log
2
2
 
3
- ## [v0.8.12](https://github.com/ably/ably-ruby/tree/v0.8.12)
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
 
@@ -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
- spec.add_runtime_dependency 'json'
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
- if RUBY_VERSION.match(/^2/)
44
+ unless RUBY_VERSION.match(/^1/)
41
45
  spec.add_development_dependency 'pry'
42
46
  spec.add_development_dependency 'pry-byebug'
43
47
  end
@@ -290,7 +290,14 @@ module Ably
290
290
  nonce: token_params[:nonce] || SecureRandom.hex.force_encoding('UTF-8')
291
291
  }
292
292
 
293
- token_request[:capability] = JSON.dump(token_request[:capability]) if token_request[:capability].is_a?(Hash)
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 milliseconds 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.
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 milliseconds.
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 |ms_elapsed|
205
- # puts "Ping took #{ms_elapsed}ms"
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 = (Time.now.to_f * 1000 - started.to_f * 1000).to_i
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?
@@ -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
@@ -1,3 +1,5 @@
1
1
  module Ably
2
- VERSION = '0.8.12'
2
+ VERSION = '0.8.13'
3
+ PROTOCOL_VERSION = '0.8'
4
+ LIB_VERSION_ID = "ruby-#{Ably::VERSION}"
3
5
  end
@@ -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
- encrypted_channel_client1.publish 'example', payload
487
- encrypted_channel_client2.subscribe do |message|
488
- expect(message.data).to eql(payload)
489
- expect(message.encoding).to be_nil
490
- stop_reactor
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
- encrypted_channel_client1.publish 'example', payload
524
- unencrypted_channel_client2.subscribe do |message|
525
- expect(message.data).to_not eql(payload)
526
- expect(message.encoding).to match(/^cipher\+aes-256-cbc/)
527
- stop_reactor
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.12
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-05-23 00:00:00.000000000 Z
12
+ date: 2016-09-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine