mirror of
https://github.com/lostisland/faraday.git
synced 2025-08-10 00:03:15 -04:00
JSON and UrlEncoded request middleware now encode body conditionally
These middleware now pay attention to "Content-Type" of the request. Each will only encode the body if the content-type value matches. When a body is present but no Content-Type, the middleware higher on the stack will use its encoding. This makes it possible to keep both middlewares on the stack and choose encoding type by Content-Type switching.
This commit is contained in:
parent
37542f953a
commit
862c98344f
@ -1,9 +1,11 @@
|
||||
module Faraday
|
||||
class Request::JSON < Faraday::Middleware
|
||||
class Request::JSON < Request::UrlEncoded
|
||||
self.mime_type = 'application/json'.freeze
|
||||
|
||||
class << self
|
||||
attr_accessor :adapter
|
||||
end
|
||||
|
||||
|
||||
# loads the JSON encoder either from yajl-ruby or activesupport
|
||||
begin
|
||||
begin
|
||||
@ -21,12 +23,9 @@ module Faraday
|
||||
end
|
||||
|
||||
def call(env)
|
||||
if data = env[:body]
|
||||
env[:request_headers]['Content-Type'] = 'application/json'
|
||||
|
||||
unless data.respond_to?(:to_str)
|
||||
env[:body] = self.class.adapter.encode data
|
||||
end
|
||||
match_content_type(env) do |data|
|
||||
# encode with the first successfully loaded adapter
|
||||
env[:body] = self.class.adapter.encode data
|
||||
end
|
||||
@app.call env
|
||||
end
|
||||
|
@ -1,14 +1,31 @@
|
||||
module Faraday
|
||||
class Request::UrlEncoded < Faraday::Middleware
|
||||
def call(env)
|
||||
if data = env[:body]
|
||||
env[:request_headers]['Content-Type'] = 'application/x-www-form-urlencoded'
|
||||
class << self
|
||||
attr_accessor :mime_type
|
||||
end
|
||||
|
||||
self.mime_type = 'application/x-www-form-urlencoded'.freeze
|
||||
|
||||
unless data.respond_to?(:to_str)
|
||||
env[:body] = Faraday::Utils.build_nested_query data
|
||||
end
|
||||
def call(env)
|
||||
match_content_type(env) do |data|
|
||||
env[:body] = Faraday::Utils.build_nested_query data
|
||||
end
|
||||
@app.call env
|
||||
end
|
||||
|
||||
def match_content_type(env)
|
||||
type = request_type(env)
|
||||
|
||||
if env[:body] and (type.empty? or type == self.class.mime_type)
|
||||
env[:request_headers]['Content-Type'] ||= self.class.mime_type
|
||||
yield env[:body] unless env[:body].respond_to?(:to_str)
|
||||
end
|
||||
end
|
||||
|
||||
def request_type(env)
|
||||
type = env[:request_headers]['Content-Type'].to_s
|
||||
type = type.split(';', 2).first if type.index(';')
|
||||
type
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,8 +1,10 @@
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
||||
require 'rack/utils'
|
||||
|
||||
class RequestMiddlewareTest < Faraday::TestCase
|
||||
def setup
|
||||
@conn = Faraday.new do |b|
|
||||
b.request :url_encoded
|
||||
b.request :json
|
||||
b.adapter :test do |stub|
|
||||
stub.post('/echo') do |env|
|
||||
@ -12,30 +14,47 @@ class RequestMiddlewareTest < Faraday::TestCase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_does_nothing_without_payload
|
||||
response = @conn.post('/echo')
|
||||
assert_nil response.headers['Content-Type']
|
||||
assert response.body.empty?
|
||||
end
|
||||
|
||||
def test_encodes_hash
|
||||
response = @conn.post('/echo', { :fruit => %w[apples oranges] })
|
||||
|
||||
def test_ignores_custom_content_type
|
||||
response = @conn.post('/echo', { :some => 'data' }, 'content-type' => 'application/x-foo')
|
||||
assert_equal 'application/x-foo', response.headers['Content-Type']
|
||||
assert_equal({ :some => 'data' }, response.body)
|
||||
end
|
||||
|
||||
def test_json_encodes_hash
|
||||
response = @conn.post('/echo', { :fruit => %w[apples oranges] }, 'content-type' => 'application/json')
|
||||
assert_equal 'application/json', response.headers['Content-Type']
|
||||
assert_equal '{"fruit":["apples","oranges"]}', response.body
|
||||
end
|
||||
|
||||
def test_skips_encoding_for_strings
|
||||
response = @conn.post('/echo', '{"a":"b"}')
|
||||
|
||||
def test_json_skips_encoding_for_strings
|
||||
response = @conn.post('/echo', '{"a":"b"}', 'content-type' => 'application/json')
|
||||
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
|
||||
|
||||
|
||||
def test_url_encoded_no_header
|
||||
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
|
||||
|
||||
def test_url_encoded_with_header
|
||||
response = @conn.post('/echo', {'a'=>123}, 'content-type' => 'application/x-www-form-urlencoded')
|
||||
assert_equal 'application/x-www-form-urlencoded', response.headers['Content-Type']
|
||||
assert_equal 'a=123', response.body
|
||||
end
|
||||
|
||||
def test_url_encoded_nested
|
||||
response = @conn.post('/echo', { :user => {:name => 'Mislav', :web => 'mislav.net'} })
|
||||
assert_equal 'application/x-www-form-urlencoded', response.headers['Content-Type']
|
||||
expected = { 'user' => {'name' => 'Mislav', 'web' => 'mislav.net'} }
|
||||
assert_equal expected, Rack::Utils.parse_nested_query(response.body)
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user