1
0
Fork 0
mirror of https://github.com/jnunemaker/httparty synced 2023-03-27 23:23:07 -04:00

Fix: URL Encode keys and values in URL encoded form data

As noted in #687, the existing implementation of our querystring
construction was not valid according to the HTTP/1.1 specification,
which was noticed with an integration issue with Apache Tomcat.

This affects both the generation of Query Strings, and URL encoded form
parameters.

The solution is to ensure that we always URL-encode the keys, as well as
the values.

It appears that the existing test we had for this, "returns a Rails
style query string", was not actually quite testing what we thought it
was, as we had not tested the rendering of the raw values, only the URL
decoded ones.

Closes #697.
This commit is contained in:
Jamie Tanna 2020-04-16 17:59:11 +01:00
parent 43c69bceff
commit 3db7a4eb36
4 changed files with 10 additions and 9 deletions

View file

@ -27,7 +27,7 @@ module HTTParty
normalized_keys = normalize_keys(key, value) normalized_keys = normalize_keys(key, value)
normalized_keys.flatten.each_slice(2).inject('') do |string, (k, v)| normalized_keys.flatten.each_slice(2).inject('') do |string, (k, v)|
string + "#{k}=#{ERB::Util.url_encode(v.to_s)}&" string + "#{ERB::Util.url_encode(k)}=#{ERB::Util.url_encode(v.to_s)}&"
end end
end end

View file

@ -11,13 +11,13 @@ RSpec.describe HTTParty::HashConversions do
phones: ['111-111-1111', '222-222-2222'] phones: ['111-111-1111', '222-222-2222']
} }
} }
expect(HTTParty::HashConversions.to_params(hash)).to eq("name=bob&address[street]=111%20ruby%20ave.&address[city]=ruby%20central&address[phones][]=111-111-1111&address[phones][]=222-222-2222") expect(HTTParty::HashConversions.to_params(hash)).to eq("name=bob&address%5Bstreet%5D=111%20ruby%20ave.&address%5Bcity%5D=ruby%20central&address%5Bphones%5D%5B%5D=111-111-1111&address%5Bphones%5D%5B%5D=222-222-2222")
end end
context "nested params" do context "nested params" do
it 'creates a params string from a hash' do it 'creates a params string from a hash' do
hash = { marketing_event: { marketed_resources: [ {type:"product", id: 57474842640 } ] } } hash = { marketing_event: { marketed_resources: [ {type:"product", id: 57474842640 } ] } }
expect(HTTParty::HashConversions.to_params(hash)).to eq("marketing_event[marketed_resources][][type]=product&marketing_event[marketed_resources][][id]=57474842640") expect(HTTParty::HashConversions.to_params(hash)).to eq("marketing_event%5Bmarketed_resources%5D%5B%5D%5Btype%5D=product&marketing_event%5Bmarketed_resources%5D%5B%5D%5Bid%5D=57474842640")
end end
end end
end end
@ -27,7 +27,7 @@ RSpec.describe HTTParty::HashConversions do
it "creates a params string" do it "creates a params string" do
expect( expect(
HTTParty::HashConversions.normalize_param(:people, ["Bob Jones", "Mike Smith"]) HTTParty::HashConversions.normalize_param(:people, ["Bob Jones", "Mike Smith"])
).to eq("people[]=Bob%20Jones&people[]=Mike%20Smith&") ).to eq("people%5B%5D=Bob%20Jones&people%5B%5D=Mike%20Smith&")
end end
end end
@ -35,7 +35,7 @@ RSpec.describe HTTParty::HashConversions do
it "creates a params string" do it "creates a params string" do
expect( expect(
HTTParty::HashConversions.normalize_param(:people, []) HTTParty::HashConversions.normalize_param(:people, [])
).to eq("people[]=&") ).to eq("people%5B%5D=&")
end end
end end
@ -43,7 +43,7 @@ RSpec.describe HTTParty::HashConversions do
it "creates a params string" do it "creates a params string" do
expect( expect(
HTTParty::HashConversions.normalize_param(:person, { name: "Bob Jones" }) HTTParty::HashConversions.normalize_param(:person, { name: "Bob Jones" })
).to eq("person[name]=Bob%20Jones&") ).to eq("person%5Bname%5D=Bob%20Jones&")
end end
end end

View file

@ -15,7 +15,7 @@ RSpec.describe HTTParty::Request::Body do
context 'when params is hash' do context 'when params is hash' do
let(:params) { { people: ["Bob Jones", "Mike Smith"] } } let(:params) { { people: ["Bob Jones", "Mike Smith"] } }
let(:converted_params) { "people[]=Bob%20Jones&people[]=Mike%20Smith"} let(:converted_params) { "people%5B%5D=Bob%20Jones&people%5B%5D=Mike%20Smith"}
it { is_expected.to eq converted_params } it { is_expected.to eq converted_params }

View file

@ -89,7 +89,7 @@ RSpec.describe HTTParty::Request do
it "sets correct query string" do it "sets correct query string" do
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com', query: { fake_array: [] }) request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com', query: { fake_array: [] })
expect(request.uri).to eq(URI.parse("http://google.com/?fake_array[]=")) expect(request.uri).to eq(URI.parse("http://google.com/?fake_array%5B%5D="))
end end
end end
@ -97,7 +97,7 @@ RSpec.describe HTTParty::Request do
it "sets correct query" do it "sets correct query" do
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com', query: { fake_array: [1] }) request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com', query: { fake_array: [1] })
expect(request.uri).to eq(URI.parse("http://google.com/?fake_array[]=1")) expect(request.uri).to eq(URI.parse("http://google.com/?fake_array%5B%5D=1"))
end end
end end
end end
@ -327,6 +327,7 @@ RSpec.describe HTTParty::Request do
it "returns a Rails style query string" do it "returns a Rails style query string" do
@request.options[:query] = {foo: %w(bar baz)} @request.options[:query] = {foo: %w(bar baz)}
expect(CGI.unescape(@request.uri.query)).to eq("foo[]=bar&foo[]=baz") expect(CGI.unescape(@request.uri.query)).to eq("foo[]=bar&foo[]=baz")
expect(@request.uri.query).to eq("foo%5B%5D=bar&foo%5B%5D=baz")
end end
end end
end end