diff --git a/lib/stripe/util.rb b/lib/stripe/util.rb index f2b5da7a..c61dcadb 100644 --- a/lib/stripe/util.rb +++ b/lib/stripe/util.rb @@ -1,3 +1,5 @@ +require "cgi" + module Stripe module Util def self.objects_to_ids(h) @@ -98,17 +100,24 @@ module Stripe # `&`). def self.encode_parameters(params) Util.flatten_params(params). - map { |k,v| "#{k}=#{Util.url_encode(v)}" }.join('&') + map { |k,v| "#{url_encode(k)}=#{url_encode(v)}" }.join('&') end + # Encodes a string in a way that makes it suitable for use in a set of + # query parameters in a URI or in a set of form parameters in a request + # body. def self.url_encode(key) - URI.escape(key.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")) + CGI.escape(key.to_s). + # Don't use strict form encoding by changing the square bracket control + # characters back to their literals. This is fine by the server, and + # makes these parameter strings easier to read. + gsub('%5B', '[').gsub('%5D', ']') end def self.flatten_params(params, parent_key=nil) result = [] params.each do |key, value| - calculated_key = parent_key ? "#{parent_key}[#{url_encode(key)}]" : url_encode(key) + calculated_key = parent_key ? "#{parent_key}[#{key}]" : "#{key}" if value.is_a?(Hash) result += flatten_params(value, calculated_key) elsif value.is_a?(Array) diff --git a/test/stripe/account_test.rb b/test/stripe/account_test.rb index 85c8a8d7..0b8216ff 100644 --- a/test/stripe/account_test.rb +++ b/test/stripe/account_test.rb @@ -68,7 +68,7 @@ module Stripe @mock.expects(:post). once. - with('https://api.stripe.com/v1/accounts/acct_foo', nil, 'legal_entity[address][line1]=2%20Three%20Four&legal_entity[first_name]=Bob'). + with('https://api.stripe.com/v1/accounts/acct_foo', nil, 'legal_entity[address][line1]=2+Three+Four&legal_entity[first_name]=Bob'). returns(make_response(resp)) a = Stripe::Account.retrieve('acct_foo') diff --git a/test/stripe/api_resource_test.rb b/test/stripe/api_resource_test.rb index ac7cfbe9..34a3e402 100644 --- a/test/stripe/api_resource_test.rb +++ b/test/stripe/api_resource_test.rb @@ -230,7 +230,7 @@ module Stripe should "urlencode values in GET params" do response = make_response(make_charge_array) - @mock.expects(:get).with("#{Stripe.api_base}/v1/charges?customer=test%20customer", nil, nil).returns(response) + @mock.expects(:get).with("#{Stripe.api_base}/v1/charges?customer=test+customer", nil, nil).returns(response) charges = Stripe::Charge.list(:customer => 'test customer').data assert charges.kind_of? Array end diff --git a/test/stripe/util_test.rb b/test/stripe/util_test.rb index 301107f2..2c404fd5 100644 --- a/test/stripe/util_test.rb +++ b/test/stripe/util_test.rb @@ -21,9 +21,7 @@ module Stripe assert_equal "foo", Stripe::Util.url_encode(:foo) assert_equal "foo%2B", Stripe::Util.url_encode("foo+") assert_equal "foo%26", Stripe::Util.url_encode("foo&") - # Actually, we're going to alter the behavior of #url_encode slightly to - # simplify the form encoding path. This does not yet succeed. - # assert_equal "foo[bar]", Stripe::Util.url_encode("foo[bar]") + assert_equal "foo[bar]", Stripe::Util.url_encode("foo[bar]") end should "#flatten_params should encode parameters according to Rails convention" do