add Request::UrlEncoded middleware for "x-www-form-urlencoded" posts

This commit is contained in:
Mislav Marohnić 2011-03-02 02:36:40 +01:00
parent 401d712987
commit 37542f953a
5 changed files with 45 additions and 4 deletions

View File

@ -2,8 +2,8 @@ module Faraday
# Possibly going to extend this a bit.
#
# Faraday::Connection.new(:url => 'http://sushi.com') do |builder|
# builder.request :json # Faraday::Request::JSON
# builder.adapter :logger # Faraday::Adapter::Logger
# builder.request :url_encoded # Faraday::Request::UrlEncoded
# builder.adapter :logger # Faraday::Adapter::Logger
# end
class Builder
attr_accessor :handlers

View File

@ -13,10 +13,12 @@ module Faraday
extend AutoloadHelper
autoload_all 'faraday/request',
:JSON => 'json'
:JSON => 'json',
:UrlEncoded => 'url_encoded'
register_lookup_modules \
:json => :JSON
:json => :JSON,
:url_encoded => :UrlEncoded
def self.run(connection, request_method)
req = create

View File

@ -0,0 +1,14 @@
module Faraday
class Request::UrlEncoded < Faraday::Middleware
def call(env)
if data = env[:body]
env[:request_headers]['Content-Type'] = 'application/x-www-form-urlencoded'
unless data.respond_to?(:to_str)
env[:body] = Faraday::Utils.build_nested_query data
end
end
@app.call env
end
end
end

View File

@ -22,6 +22,23 @@ module Faraday
# Make Rack::Utils build_query method public.
public :build_query
# Override Rack's version since it doesn't handle non-String values
def build_nested_query(value, prefix = nil)
case value
when Array
value.map { |v| build_nested_query(v, "#{prefix}[]") }.join("&")
when Hash
value.map { |k, v|
build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
}.join("&")
when NilClass
prefix
else
raise ArgumentError, "value must be a Hash" if prefix.nil?
"#{prefix}=#{escape(value)}"
end
end
# Be sure to URI escape '+' symbols to %2B. Otherwise, they get interpreted
# as spaces.
def escape(s)

View File

@ -30,4 +30,12 @@ class RequestMiddlewareTest < Faraday::TestCase
assert_equal 'application/json', response.headers['Content-Type']
assert_equal '{"a":"b"}', response.body
end
def test_url_encoded
@conn.builder.swap Faraday::Request::JSON, Faraday::Request::UrlEncoded
response = @conn.post('/echo', { :fruit => %w[apples oranges] })
assert_equal 'application/x-www-form-urlencoded', response.headers['Content-Type']
assert_equal 'fruit[]=apples&fruit[]=oranges', response.body
end
end