diff --git a/CHANGELOG.md b/CHANGELOG.md index c651ba5..0dfe8fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## Unreleased + +* [FIXED] Use `MultiJSON.generate` and `MultiJSON.parse` to avoid multi_json 1.21+ deprecation warnings. +* [CHANGED] Require multi_json 1.21 or later within the 1.x series. + ## 2.1.1 * [FIXED] Fix MultiJson deprecation warnings (encode/decode → dump/load) diff --git a/lib/pusher/channel.rb b/lib/pusher/channel.rb index 57e88fc..4337041 100644 --- a/lib/pusher/channel.rb +++ b/lib/pusher/channel.rb @@ -156,7 +156,7 @@ def authentication_string(socket_id, custom_string = nil) # @private Custom data is sent to server as JSON-encoded string # def authenticate(socket_id, custom_data = nil) - custom_data = MultiJson.dump(custom_data) if custom_data + custom_data = MultiJSON.generate(custom_data) if custom_data auth = authentication_string(socket_id, custom_data) r = {:auth => auth} r[:channel_data] = custom_data if custom_data diff --git a/lib/pusher/client.rb b/lib/pusher/client.rb index 00194b2..2bab49e 100644 --- a/lib/pusher/client.rb +++ b/lib/pusher/client.rb @@ -374,7 +374,7 @@ def authenticate(channel_name, socket_id, custom_data = nil) def authenticate_user(socket_id, user_data) validate_user_data(user_data) - custom_data = MultiJson.dump(user_data) + custom_data = MultiJSON.generate(user_data) auth = authentication_string(socket_id, custom_data) { auth:, user_data: custom_data } @@ -461,7 +461,7 @@ def trigger_batch_params(events) # JSON-encode the data if it's not a string def encode_data(data) return data if data.is_a? String - MultiJson.dump(data) + MultiJSON.generate(data) end # Encrypts a message with a key derived from the master key and channel @@ -480,7 +480,7 @@ def encrypt(channel_name, encoded_data) nonce = RbNaCl::Random.random_bytes(secret_box.nonce_bytes) ciphertext = secret_box.encrypt(nonce, encoded_data) - MultiJson.dump({ + MultiJSON.generate({ "nonce" => Base64::strict_encode64(nonce), "ciphertext" => Base64::strict_encode64(ciphertext), }) diff --git a/lib/pusher/request.rb b/lib/pusher/request.rb index 4edf9ff..6dbe288 100644 --- a/lib/pusher/request.rb +++ b/lib/pusher/request.rb @@ -86,9 +86,9 @@ def send_async def handle_response(status_code, body) case status_code when 200 - return symbolize_first_level(MultiJson.load(body)) + return symbolize_first_level(MultiJSON.parse(body)) when 202 - return body.empty? ? true : symbolize_first_level(MultiJson.load(body)) + return body.empty? ? true : symbolize_first_level(MultiJSON.parse(body)) when 400 raise Error, "Bad request: #{body}" when 401 diff --git a/lib/pusher/resource.rb b/lib/pusher/resource.rb index 8a0cf2b..30ea174 100644 --- a/lib/pusher/resource.rb +++ b/lib/pusher/resource.rb @@ -14,12 +14,12 @@ def get_async(params) end def post(params) - body = MultiJson.dump(params) + body = MultiJSON.generate(params) create_request(:post, {}, body).send_sync end def post_async(params) - body = MultiJson.dump(params) + body = MultiJSON.generate(params) create_request(:post, {}, body).send_async end diff --git a/lib/pusher/webhook.rb b/lib/pusher/webhook.rb index 71714ba..d6e5205 100644 --- a/lib/pusher/webhook.rb +++ b/lib/pusher/webhook.rb @@ -88,7 +88,7 @@ def data @data ||= begin case @content_type when 'application/json' - MultiJson.load(@body) + MultiJSON.parse(@body) else raise "Unknown Content-Type (#{@content_type})" end diff --git a/pusher.gemspec b/pusher.gemspec index d4cc697..42a462f 100644 --- a/pusher.gemspec +++ b/pusher.gemspec @@ -15,7 +15,7 @@ Gem::Specification.new do |s| s.required_ruby_version = ">= 3.1" - s.add_dependency "multi_json", "~> 1.15" + s.add_dependency "multi_json", "~> 1.21" s.add_dependency 'pusher-signature', "~> 0.1.8" s.add_dependency "httpclient", "~> 2.8" s.add_dependency "jruby-openssl" if defined?(JRUBY_VERSION) diff --git a/spec/channel_spec.rb b/spec/channel_spec.rb index aef45d1..d72c071 100644 --- a/spec/channel_spec.rb +++ b/spec/channel_spec.rb @@ -133,7 +133,7 @@ def authentication_string(*data) end it 'should return a hash with signature including custom data and data as json string' do - allow(MultiJson).to receive(:dump).with(@custom_data).and_return 'a json string' + allow(MultiJSON).to receive(:generate).with(@custom_data).and_return 'a json string' response = @channel.authenticate('1.1', @custom_data) diff --git a/spec/client_spec.rb b/spec/client_spec.rb index 96f41b2..8f4b6b3 100644 --- a/spec/client_spec.rb +++ b/spec/client_spec.rb @@ -235,7 +235,7 @@ api_path = %r{/apps/20/channels} stub_request(:get, api_path).to_return({ :status => 200, - :body => MultiJson.dump('channels' => { + :body => MultiJSON.generate('channels' => { "channel1" => {}, "channel2" => {} }) @@ -254,7 +254,7 @@ api_path = %r{/apps/20/channels/mychannel} stub_request(:get, api_path).to_return({ :status => 200, - :body => MultiJson.dump({ + :body => MultiJSON.generate({ 'occupied' => false, }) }) @@ -288,7 +288,7 @@ stub_request(:get, api_path) .to_return({ :status => 500, :body => "Server error" }) .then - .to_return({ :status => 200, :body => MultiJson.dump({ 'occupied' => false }) }) + .to_return({ :status => 200, :body => MultiJSON.generate({ 'occupied' => false }) }) expect { @client.channel_info('mychannel') }.to raise_error(Pusher::Error) expect(@client.channel_info('mychannel')).to eq({ :occupied => false }) @@ -298,7 +298,7 @@ api_path = %r{/apps/20/channels/mychannel} stub_request(:get, api_path).to_return({ :status => 200, - :body => MultiJson.dump({ 'occupied' => false }) + :body => MultiJSON.generate({ 'occupied' => false }) }) http_client = @client.sync_http_client @@ -313,7 +313,7 @@ api_path = %r{/apps/20/channels/mychannel/users} stub_request(:get, api_path).to_return({ :status => 200, - :body => MultiJson.dump({ + :body => MultiJSON.generate({ 'users' => [{ 'id' => 1 }] }) }) @@ -329,7 +329,7 @@ end it 'should return a hash with signature including custom data and data as json string' do - allow(MultiJson).to receive(:dump).with(@custom_data).and_return 'a json string' + allow(MultiJSON).to receive(:generate).with(@custom_data).and_return 'a json string' response = @client.authenticate('test_channel', '1.1', @custom_data) @@ -340,7 +340,7 @@ end it 'should include a shared_secret if the private-encrypted channel' do - allow(MultiJson).to receive(:dump).with(@custom_data).and_return 'a json string' + allow(MultiJSON).to receive(:generate).with(@custom_data).and_return 'a json string' @client.instance_variable_set(:@encryption_master_key, '3W1pfB/Etr+ZIlfMWwZP3gz8jEeCt4s2pe6Vpr+2c3M=') response = @client.authenticate('private-encrypted-test_channel', '1.1', @custom_data) @@ -360,7 +360,7 @@ end it 'should return a hash with signature including custom data and data as json string' do - allow(MultiJson).to receive(:dump).with(@user_data).and_return 'a json string' + allow(MultiJSON).to receive(:generate).with(@user_data).and_return 'a json string' response = @client.authenticate_user('1.1', @user_data) @@ -377,7 +377,7 @@ @api_path = %r{/apps/20/events} stub_request(:post, @api_path).to_return({ :status => 200, - :body => MultiJson.dump({}) + :body => MultiJSON.generate({}) }) end @@ -399,7 +399,7 @@ :socket_id => "12.34" }) expect(WebMock).to have_requested(:post, @api_path).with { |req| - parsed = MultiJson.load(req.body) + parsed = MultiJSON.parse(req.body) expect(parsed["name"]).to eq('event') expect(parsed["channels"]).to eq(["mychannel", "c2"]) expect(parsed["socket_id"]).to eq('12.34') @@ -409,14 +409,14 @@ it "should convert non string data to JSON before posting" do @client.trigger(['mychannel'], 'event', {'some' => 'data'}) expect(WebMock).to have_requested(:post, @api_path).with { |req| - expect(MultiJson.load(req.body)["data"]).to eq('{"some":"data"}') + expect(MultiJSON.parse(req.body)["data"]).to eq('{"some":"data"}') } end it "should accept a single channel as well as an array" do @client.trigger('mychannel', 'event', {'some' => 'data'}) expect(WebMock).to have_requested(:post, @api_path).with { |req| - expect(MultiJson.load(req.body)["channels"]).to eq(['mychannel']) + expect(MultiJSON.parse(req.body)["channels"]).to eq(['mychannel']) } end @@ -427,7 +427,7 @@ @client.trigger('mychannel', 'event', {'some' => 'data'}) }.to raise_error(Pusher::ConfigurationError) expect(WebMock).not_to have_requested(:post, @api_path).with { |req| - expect(MultiJson.load(req.body)["channels"]).to eq(['mychannel']) + expect(MultiJSON.parse(req.body)["channels"]).to eq(['mychannel']) } end end @@ -459,13 +459,13 @@ ) expect(WebMock).to have_requested(:post, @api_path).with { |req| - data = MultiJson.load(MultiJson.load(req.body)["data"]) + data = MultiJSON.parse(MultiJSON.parse(req.body)["data"]) key = RbNaCl::Hash.sha256( 'private-encrypted-channel' + encryption_master_key ) - expect(MultiJson.load(RbNaCl::SecretBox.new(key).decrypt( + expect(MultiJSON.parse(RbNaCl::SecretBox.new(key).decrypt( Base64.strict_decode64(data["nonce"]), Base64.strict_decode64(data["ciphertext"]), ))).to eq({ 'some' => 'data' }) @@ -478,7 +478,7 @@ @api_path = %r{/apps/20/batch_events} stub_request(:post, @api_path).to_return({ :status => 200, - :body => MultiJson.dump({}) + :body => MultiJSON.generate({}) }) end @@ -493,7 +493,7 @@ {channel: 'mychannel', name: 'event', data: 'already encoded'}, ) expect(WebMock).to have_requested(:post, @api_path).with { |req| - parsed = MultiJson.load(req.body) + parsed = MultiJSON.parse(req.body) expect(parsed).to eq( "batch" => [ { "channel" => "mychannel", "name" => "event", "data" => "{\"some\":\"data\"}"}, @@ -529,19 +529,19 @@ ) expect(WebMock).to have_requested(:post, @api_path).with { |req| - batch = MultiJson.load(req.body)["batch"] + batch = MultiJSON.parse(req.body)["batch"] expect(batch.length).to eq(2) expect(batch[0]["channel"]).to eq("private-encrypted-channel") expect(batch[0]["name"]).to eq("event") - data = MultiJson.load(batch[0]["data"]) + data = MultiJSON.parse(batch[0]["data"]) key = RbNaCl::Hash.sha256( 'private-encrypted-channel' + encryption_master_key ) - expect(MultiJson.load(RbNaCl::SecretBox.new(key).decrypt( + expect(MultiJSON.parse(RbNaCl::SecretBox.new(key).decrypt( Base64.strict_decode64(data["nonce"]), Base64.strict_decode64(data["ciphertext"]), ))).to eq({ 'some' => 'data' }) @@ -558,7 +558,7 @@ @api_path = %r{/apps/20/events} stub_request(:post, @api_path).to_return({ :status => 200, - :body => MultiJson.dump({}) + :body => MultiJSON.generate({}) }) end @@ -577,7 +577,7 @@ :socket_id => "12.34" }).callback { expect(WebMock).to have_requested(:post, @api_path).with { |req| - expect(MultiJson.load(req.body)["socket_id"]).to eq('12.34') + expect(MultiJSON.parse(req.body)["socket_id"]).to eq('12.34') } EM.stop } @@ -588,7 +588,7 @@ EM.run { @client.trigger_async('mychannel', 'event', {'some' => 'data'}).callback { expect(WebMock).to have_requested(:post, @api_path).with { |req| - expect(MultiJson.load(req.body)["data"]).to eq('{"some":"data"}') + expect(MultiJSON.parse(req.body)["data"]).to eq('{"some":"data"}') } EM.stop } @@ -620,7 +620,7 @@ it "should format the respose hash with symbols at first level" do stub_request(verb, @url_regexp).to_return({ :status => 200, - :body => MultiJson.dump({'something' => {'a' => 'hash'}}) + :body => MultiJSON.generate({'something' => {'a' => 'hash'}}) }) expect(call_api).to eq({ :something => {'a' => 'hash'} @@ -751,7 +751,7 @@ EM.run { stub_request(verb, @url_regexp).to_return({ :status => 200, - :body => MultiJson.dump({'something' => {'a' => 'hash'}}) + :body => MultiJSON.generate({'something' => {'a' => 'hash'}}) }) call_api.callback { |response| expect(response).to eq({ diff --git a/spec/web_hook_spec.rb b/spec/web_hook_spec.rb index 10118d8..1a3fdb3 100644 --- a/spec/web_hook_spec.rb +++ b/spec/web_hook_spec.rb @@ -19,7 +19,7 @@ 'HTTP_X_PUSHER_KEY' => '1234', 'HTTP_X_PUSHER_SIGNATURE' => 'asdf', 'CONTENT_TYPE' => 'application/json', - 'rack.input' => StringIO.new(MultiJson.dump(@hook_data)) + 'rack.input' => StringIO.new(MultiJSON.generate(@hook_data)) }) wh = Pusher::WebHook.new(request) expect(wh.key).to eq('1234') @@ -32,7 +32,7 @@ :key => '1234', :signature => 'asdf', :content_type => 'application/json', - :body => MultiJson.dump(@hook_data), + :body => MultiJSON.generate(@hook_data), } wh = Pusher::WebHook.new(request) expect(wh.key).to eq('1234') @@ -43,7 +43,7 @@ describe "after initialization" do before :each do - @body = MultiJson.dump(@hook_data) + @body = MultiJSON.generate(@hook_data) request = { :key => '1234', :signature => hmac('asdf', @body),