diff --git a/.pubnub.yml b/.pubnub.yml index b732f828b..8648646d6 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -1,6 +1,13 @@ --- -version: "6.0.1" +version: "6.0.2" changelog: + - date: 2026-03-03 + version: v6.0.2 + changes: + - type: improvement + text: "Add `.uniq` calls when building subscribe URL path and channel-group query parameter to prevent duplicate channels and channel groups from leaking into HTTP requests." + - type: improvement + text: "Add `.uniq` calls when building heartbeat URL path and channel-group query parameter to prevent duplicate channels and channel groups from leaking into HTTP requests." - date: 2025-11-04 version: v6.0.1 changes: @@ -627,7 +634,7 @@ sdks: - x86-64 - distribution-type: package distribution-repository: RubyGems - package-name: pubnub-6.0.1.gem + package-name: pubnub-6.0.2.gem location: https://rubygems.org/gems/pubnub requires: - name: addressable @@ -732,8 +739,8 @@ sdks: - x86-64 - distribution-type: library distribution-repository: GitHub release - package-name: pubnub-6.0.1.gem - location: https://github.com/pubnub/ruby/releases/download/v6.0.1/pubnub-6.0.1.gem + package-name: pubnub-6.0.2.gem + location: https://github.com/pubnub/ruby/releases/download/v6.0.2/pubnub-6.0.2.gem requires: - name: addressable min-version: 2.0.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 068995f72..2ae46a5bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,38 +1,45 @@ -## v6.0.1 -November 04 2025 - -#### Fixed -- Send proper object for `state` with the `heartbeat` request. - -#### Modified -- Don't cap `limit` and let the server perform value validation. -- Replace legacy timetoken query parameter with subscribe v2 parameters. - -## v6.0.0 -October 15 2025 - -#### Added -- BREAKING CHANGES: Add 'limit' and 'offset' parameters for 'here_now' for pagination support. - -## v5.6.0 -September 11 2025 - -#### Added -- Add the `encode_channels` parameter for `fetch` to enable or disable channel names percent-encoding in response. - -## v5.5.1 -September 08 2025 - -#### Fixed -- Fix the issue introduced by RuboCop linter suggestion acceptance, which caused a wrong number of arguments error. - -## v5.5.0 -January 28 2025 - -#### Added -- Add the ability to specify `type` and `status` fields for `channel metadata`, `uuid metadata`, `member`, and `membership`. -- Add missing `include` options for App Context APIs: `custom`, `status`, `type`, `uuid_status`, `uuid_type`, `channel_status`, and `channel_type`. - +## v6.0.2 +March 03 2026 + +#### Modified +- Add `.uniq` calls when building subscribe URL path and channel-group query parameter to prevent duplicate channels and channel groups from leaking into HTTP requests. +- Add `.uniq` calls when building heartbeat URL path and channel-group query parameter to prevent duplicate channels and channel groups from leaking into HTTP requests. + +## v6.0.1 +November 04 2025 + +#### Fixed +- Send proper object for `state` with the `heartbeat` request. + +#### Modified +- Don't cap `limit` and let the server perform value validation. +- Replace legacy timetoken query parameter with subscribe v2 parameters. + +## v6.0.0 +October 15 2025 + +#### Added +- BREAKING CHANGES: Add 'limit' and 'offset' parameters for 'here_now' for pagination support. + +## v5.6.0 +September 11 2025 + +#### Added +- Add the `encode_channels` parameter for `fetch` to enable or disable channel names percent-encoding in response. + +## v5.5.1 +September 08 2025 + +#### Fixed +- Fix the issue introduced by RuboCop linter suggestion acceptance, which caused a wrong number of arguments error. + +## v5.5.0 +January 28 2025 + +#### Added +- Add the ability to specify `type` and `status` fields for `channel metadata`, `uuid metadata`, `member`, and `membership`. +- Add missing `include` options for App Context APIs: `custom`, `status`, `type`, `uuid_status`, `uuid_type`, `channel_status`, and `channel_type`. + ## v5.4.0 January 07 2025 diff --git a/Gemfile.lock b/Gemfile.lock index 48059c292..12f588e0b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - pubnub (6.0.1) + pubnub (6.0.2) addressable (>= 2.0.0) concurrent-ruby (~> 1.3.4) concurrent-ruby-edge (~> 0.7.1) diff --git a/VERSION b/VERSION index 5fe607230..9b9a24420 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.0.1 +6.0.2 diff --git a/fixtures/vcr_cassettes/examples/presence/0.yml b/fixtures/vcr_cassettes/examples/presence/0.yml index 43483dc3b..9ae00f43b 100644 --- a/fixtures/vcr_cassettes/examples/presence/0.yml +++ b/fixtures/vcr_cassettes/examples/presence/0.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: http://ps.pndsn.com/v2/subscribe/sub-a-mock-key/demo-pnpres,demo-pnpres,demo.*-pnpres/0?auth=ruby-test-auth-client-one&pnsdk=PubNub-Ruby/4.1.0beta1&uuid=ruby-test-uuid-client-one + uri: http://ps.pndsn.com/v2/subscribe/sub-a-mock-key/demo-pnpres,demo.*-pnpres/0?auth=ruby-test-auth-client-one&pnsdk=PubNub-Ruby/4.1.0beta1&uuid=ruby-test-uuid-client-one body: encoding: UTF-8 string: '' @@ -39,7 +39,7 @@ http_interactions: recorded_at: Wed, 08 Jun 2016 16:38:11 GMT - request: method: get - uri: http://ps.pndsn.com/v2/subscribe/sub-a-mock-key/demo-pnpres,demo-pnpres,demo.*-pnpres/0?auth=ruby-test-auth-client-one&pnsdk=PubNub-Ruby/4.1.0beta1&tr=3&tt=14654038913920233&uuid=ruby-test-uuid-client-one + uri: http://ps.pndsn.com/v2/subscribe/sub-a-mock-key/demo-pnpres,demo.*-pnpres/0?auth=ruby-test-auth-client-one&pnsdk=PubNub-Ruby/4.1.0beta1&tr=3&tt=14654038913920233&uuid=ruby-test-uuid-client-one body: encoding: UTF-8 string: '' diff --git a/fixtures/vcr_cassettes/examples/presence/1.yml b/fixtures/vcr_cassettes/examples/presence/1.yml index c343d6528..39fad41db 100644 --- a/fixtures/vcr_cassettes/examples/presence/1.yml +++ b/fixtures/vcr_cassettes/examples/presence/1.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: http://ps.pndsn.com/v2/subscribe/sub-a-mock-key/demo-pnpres,demo-pnpres,demo.*-pnpres/0?auth=ruby-test-auth-client-one&pnsdk=PubNub-Ruby/4.1.0beta1&uuid=ruby-test-uuid-client-one + uri: http://ps.pndsn.com/v2/subscribe/sub-a-mock-key/demo-pnpres,demo.*-pnpres/0?auth=ruby-test-auth-client-one&pnsdk=PubNub-Ruby/4.1.0beta1&uuid=ruby-test-uuid-client-one body: encoding: UTF-8 string: '' @@ -39,7 +39,7 @@ http_interactions: recorded_at: Wed, 08 Jun 2016 16:38:13 GMT - request: method: get - uri: http://ps.pndsn.com/v2/subscribe/sub-a-mock-key/demo-pnpres,demo-pnpres,demo.*-pnpres/0?auth=ruby-test-auth-client-one&pnsdk=PubNub-Ruby/4.1.0beta1&tr=3&tt=14654038931856126&uuid=ruby-test-uuid-client-one + uri: http://ps.pndsn.com/v2/subscribe/sub-a-mock-key/demo-pnpres,demo.*-pnpres/0?auth=ruby-test-auth-client-one&pnsdk=PubNub-Ruby/4.1.0beta1&tr=3&tt=14654038931856126&uuid=ruby-test-uuid-client-one body: encoding: UTF-8 string: '' diff --git a/fixtures/vcr_cassettes/examples/presence/2.yml b/fixtures/vcr_cassettes/examples/presence/2.yml index c7d980ce7..06e882d65 100644 --- a/fixtures/vcr_cassettes/examples/presence/2.yml +++ b/fixtures/vcr_cassettes/examples/presence/2.yml @@ -2,7 +2,7 @@ http_interactions: - request: method: get - uri: http://ps.pndsn.com/v2/subscribe/sub-a-mock-key/demo-pnpres,demo-pnpres,demo.*-pnpres/0?auth=ruby-test-auth-client-one&pnsdk=PubNub-Ruby/4.1.0beta1&uuid=ruby-test-uuid-client-one + uri: http://ps.pndsn.com/v2/subscribe/sub-a-mock-key/demo-pnpres,demo.*-pnpres/0?auth=ruby-test-auth-client-one&pnsdk=PubNub-Ruby/4.1.0beta1&uuid=ruby-test-uuid-client-one body: encoding: UTF-8 string: '' @@ -39,7 +39,7 @@ http_interactions: recorded_at: Wed, 08 Jun 2016 16:38:10 GMT - request: method: get - uri: http://ps.pndsn.com/v2/subscribe/sub-a-mock-key/demo-pnpres,demo-pnpres,demo.*-pnpres/0?auth=ruby-test-auth-client-one&pnsdk=PubNub-Ruby/4.1.0beta1&tr=3&tt=14654038905501214&uuid=ruby-test-uuid-client-one + uri: http://ps.pndsn.com/v2/subscribe/sub-a-mock-key/demo-pnpres,demo.*-pnpres/0?auth=ruby-test-auth-client-one&pnsdk=PubNub-Ruby/4.1.0beta1&tr=3&tt=14654038905501214&uuid=ruby-test-uuid-client-one body: encoding: UTF-8 string: '' diff --git a/fixtures/vcr_cassettes/lib/events/heartbeat-unique.yml b/fixtures/vcr_cassettes/lib/events/heartbeat-unique.yml new file mode 100644 index 000000000..527cb8f7b --- /dev/null +++ b/fixtures/vcr_cassettes/lib/events/heartbeat-unique.yml @@ -0,0 +1,46 @@ +--- +http_interactions: +- request: + method: get + uri: http://ps.pndsn.com/v2/presence/sub-key/sub-a-mock-key/channel/demo,demo-b/heartbeat?auth=ruby-test-auth&channel-group=grp-a&heartbeat=&pnsdk=PubNub-Ruby/4.1.0&uuid=ruby-test-uuid + body: + encoding: UTF-8 + string: '' + headers: + User-Agent: + - HTTPClient/1.0 (2.8.0, ruby 2.0.0 (2015-04-13)) + Accept: + - '*/*' + Date: + - Thu, 12 May 2016 16:32:47 GMT + response: + status: + code: 200 + message: OK + headers: + Date: + - Thu, 12 May 2016 16:32:47 GMT + Content-Type: + - text/javascript; charset="UTF-8" + Content-Length: + - '55' + Connection: + - keep-alive + Access-Control-Allow-Origin: + - '*' + Access-Control-Allow-Methods: + - OPTIONS, GET, POST + Cache-Control: + - no-cache + Accept-Ranges: + - bytes + Age: + - '0' + Server: + - Pubnub Presence + body: + encoding: UTF-8 + string: '{"status": 200, "message": "OK", "service": "Presence"}' + http_version: + recorded_at: Thu, 12 May 2016 16:32:47 GMT +recorded_with: VCR 3.0.1 diff --git a/lib/pubnub/events/heartbeat.rb b/lib/pubnub/events/heartbeat.rb index bf37946e2..a4a341913 100644 --- a/lib/pubnub/events/heartbeat.rb +++ b/lib/pubnub/events/heartbeat.rb @@ -25,7 +25,7 @@ def path 'sub-key', @subscribe_key, 'channel', - Formatter.channels_for_url(@channel), + Formatter.channels_for_url(@channel.uniq), 'heartbeat' ].join('/') end @@ -37,7 +37,7 @@ def parameters(*_args) parameters.delete(:state) if parameters[:state] == '%7B%7D' end parameters[:heartbeat] = @heartbeat - parameters['channel-group'] = @group.join(',') unless @group.blank? + parameters['channel-group'] = @group.uniq.join(',') unless @group.blank? parameters end diff --git a/lib/pubnub/subscribe_event.rb b/lib/pubnub/subscribe_event.rb index 61da05724..bc7bb8a7f 100644 --- a/lib/pubnub/subscribe_event.rb +++ b/lib/pubnub/subscribe_event.rb @@ -124,7 +124,7 @@ def path 'v2', 'subscribe', @subscribe_key, - Pubnub::Formatter.channels_for_url(@channel + @wildcard_channel), + Pubnub::Formatter.channels_for_url((@channel + @wildcard_channel).uniq), 0 ].join('/').gsub(/\?/, '%3F') end @@ -151,7 +151,7 @@ def add_timetoken_to_params(params) end def add_group_to_params(params) - params['channel-group'] = @group.join(',') unless @group.empty? + params['channel-group'] = @group.uniq.join(',') unless @group.empty? params end diff --git a/lib/pubnub/version.rb b/lib/pubnub/version.rb index 897f5a6e5..820408de2 100644 --- a/lib/pubnub/version.rb +++ b/lib/pubnub/version.rb @@ -1,4 +1,4 @@ # Toplevel Pubnub module. module Pubnub - VERSION = '6.0.1'.freeze + VERSION = '6.0.2'.freeze end diff --git a/spec/lib/events/heartbeat_spec.rb b/spec/lib/events/heartbeat_spec.rb index 5e17dc5cc..40ab897e3 100644 --- a/spec/lib/events/heartbeat_spec.rb +++ b/spec/lib/events/heartbeat_spec.rb @@ -42,6 +42,19 @@ end end + it "sends unique channels and channel groups even when duplicates are provided" do + VCR.use_cassette("lib/events/heartbeat-unique", record: :once) do + envelope = @pubnub.heartbeat( + channel: ['demo', 'demo', 'demo-b'], + channel_group: ['grp-a', 'grp-a'], + ).value + + expect(envelope.status[:client_request].to_s).to include('/channel/demo,demo-b/') + expect(envelope.status[:client_request].to_s).to include('channel-group=grp-a') + expect(envelope.status[:client_request].to_s).not_to include('channel-group=grp-a,grp-a') + end + end + it "forms valid ErrorEnvelope on error" do VCR.use_cassette("lib/events/heartbeat-error", record: :once) do envelope = @pubnub.heartbeat(