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

Allow custom query string normalization

Useful for changing the Rails-style querystrings, i.e.
key[]=1&key[]=2 could become key=1&key=2

Closes gh-8
This commit is contained in:
Sandro Turriate 2010-10-29 09:09:47 -04:00
parent 2f42d99a63
commit a33741df46
3 changed files with 89 additions and 3 deletions

View file

@ -201,6 +201,37 @@ module HTTParty
default_options[:pem] = pem_contents
end
# Override the way query strings are normalized.
# Helpful for overriding the default rails normalization of Array queries.
#
# For a query:
# get '/', :query => {:selected_ids => [1,2,3]}
#
# The default query string normalizer returns:
# /?selected_ids[]=1&selected_ids[]=2&selected_ids[]=3
#
# Let's change it to this:
# /?selected_ids=1&selected_ids=2&selected_ids=3
#
# Pass a Proc to the query normalizer which accepts the yielded query.
#
# @example Modifying Array query strings
# class ServiceWrapper
# include HTTParty
#
# query_string_normalizer proc { |query|
# query.map do |key, value|
# value.map {|v| "#{key}=#{v}"}
# end.join('&')
# }
# end
#
# @param [Proc] normalizer the new normalizer
# @yield [Hash] query hash option
def query_string_normalizer(normalizer)
default_options[:query_string_normalizer] = normalizer
end
# Allows setting an OpenSSL certificate authority file
#
# class Foo

View file

@ -103,7 +103,7 @@ module HTTParty
end
def body
options[:body].is_a?(Hash) ? options[:body].to_params : options[:body]
options[:body].is_a?(Hash) ? normalize_query(options[:body]) : options[:body]
end
def credentials
@ -118,6 +118,18 @@ module HTTParty
credentials[:password]
end
def normalize_query(query)
if query_string_normalizer
query_string_normalizer.call(query)
else
query.to_params
end
end
def query_string_normalizer
options[:query_string_normalization]
end
def setup_raw_request
@raw_request = http_method.new(uri.request_uri)
@raw_request.body = body if body
@ -146,12 +158,13 @@ module HTTParty
query_string_parts << uri.query unless uri.query.nil?
if options[:query].is_a?(Hash)
query_string_parts << options[:default_params].merge(options[:query]).to_params
query_string_parts << normalize_query(options[:default_params].merge(options[:query]))
else
query_string_parts << options[:default_params].to_params unless options[:default_params].empty?
query_string_parts << normalize_query(options[:default_params]) unless options[:default_params].empty?
query_string_parts << options[:query] unless options[:query].nil?
end
query_string_parts.size > 0 ? query_string_parts.join('&') : nil
end

View file

@ -5,6 +5,18 @@ describe HTTParty::Request do
@request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', :format => :xml)
end
let(:array_normalization_proc) do
proc do |query|
query.map do |key, value|
if value.is_a?(Array)
value.map {|v| "#{key}=#{v}"}
else
{key => value}.to_params
end
end.flatten.sort.join('&')
end
end
describe "initialization" do
it "sets parser to HTTParty::Parser" do
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com')
@ -74,6 +86,36 @@ describe HTTParty::Request do
@request.options[:default_params] = {}
@request.uri.query.should be_nil
end
it "respects the query string normalization proc" do
@request.options[:query_string_normalization] = array_normalization_proc
@request.options[:query] = {:page => 1, :foo => %w(bar baz)}
URI.unescape(@request.uri.query).should == "foo=bar&foo=baz&page=1"
end
context "when representing an array" do
it "doesn't modify strings" do
@request.options[:query] = "foo=bar&foo=baz"
URI.unescape(@request.uri.query).should == "foo=bar&foo=baz"
end
it "converts a ruby array into a Rails supported query string" do
@request.options[:query] = {:foo => %w(bar baz)}
URI.unescape(@request.uri.query).should == "foo[]=bar&foo[]=baz"
end
end
end
end
describe "#setup_raw_request" do
context "when query_string_normalization is set" do
it "sets the body to the return value of the proc" do
@request.options[:query_string_normalization] = array_normalization_proc
@request.options[:body] = {:page => 1, :foo => %w(bar baz)}
@request.send(:setup_raw_request)
body = @request.instance_variable_get(:@raw_request).body
URI.unescape(body).should == "foo=bar&foo=baz&page=1"
end
end
end