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 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