like :request_headers, env[:response_headers] is now case-insensitive

This commit is contained in:
Mislav Marohnić 2011-03-27 00:23:20 +01:00
parent 50da50306e
commit 8dccfc6117
11 changed files with 82 additions and 94 deletions

View File

@ -21,10 +21,8 @@ module Faraday
super
@session.__send__(env[:method], env[:url].request_uri, env[:body], env[:request_headers])
resp = @session.response
env.update \
:status => resp.status,
:response_headers => resp.headers,
:body => resp.body
env.update :status => resp.status, :body => resp.body
env[:response_headers].update resp.headers
@app.call env
end
end

View File

@ -21,14 +21,8 @@ module Faraday
:headers => env[:request_headers],
:body => env[:body]
env.update \
:status => resp.status.to_i,
:response_headers => {},
:body => resp.body
resp.headers.each do |key, value|
env[:response_headers][key.downcase] = value
end
env.update :status => resp.status.to_i, :body => resp.body
env[:response_headers].update resp.headers
@app.call env
rescue ::Excon::Errors::SocketError

View File

@ -53,15 +53,10 @@ module Faraday
raise Error::ConnectionFailed, $!
end
response_headers = {}
http_response.each_header do |key, value|
response_headers[key] = value
env[:response_headers][key] = value
end
env.update \
:status => http_response.code.to_i,
:response_headers => response_headers,
:body => http_response.body
env.update :status => http_response.code.to_i, :body => http_response.body
@app.call env
end

View File

@ -25,10 +25,8 @@ module Faraday
raise Error::ConnectionFailed, $!
end
env.update \
:status => response.status,
:response_headers => response.headers.inject({}) { |memo, (k, v)| memo[k.downcase] = v; memo },
:body => response.body
env.update :status => response.status, :body => response.body
env[:response_headers].update response.headers
@app.call env
end

View File

@ -31,10 +31,8 @@ module Faraday
is_parallel = !!env[:parallel_manager]
req.on_complete do |resp|
env.update \
:status => resp.code,
:response_headers => parse_response_headers(resp.headers),
:body => resp.body
env.update :status => resp.code, :body => resp.body
env[:response_headers].parse resp.headers
env[:response].finish(env) if is_parallel
end
@ -46,15 +44,6 @@ module Faraday
rescue Errno::ECONNREFUSED
raise Error::ConnectionFailed, $!
end
def parse_response_headers(header_string)
return {} unless header_string && !header_string.empty?
Hash[*header_string.split(/\r\n/).
tap { |a| a.shift }. # drop the HTTP status line
map { |h| h.split(/:\s+/,2) }. # split key and value
reject { |(k, v)| k.nil? }. # Ignore blank lines
map { |(k, v)| [k.downcase, v] }.flatten]
end
end
end
end

View File

@ -22,7 +22,7 @@ module Faraday
options = url
url = options[:url]
end
@headers = HeaderHash.new
@headers = Headers.new
@params = {}
@options = options[:request] || {}
@ssl = options[:ssl] || {}

View File

@ -73,6 +73,7 @@ module Faraday
:body => body,
:url => connection.build_url(path, env_params),
:request_headers => env_headers,
:response_headers => Utils::Headers.new,
:parallel_manager => connection.parallel_manager,
:request => connection.options.merge(:proxy => connection.proxy),
:ssl => connection.ssl}

View File

@ -6,19 +6,37 @@ module Faraday
extend Rack::Utils
extend self
HEADERS = Hash.new do |h, k|
if k.respond_to?(:to_str)
k
else
k.to_s.split('_'). # :user_agent => %w(user agent)
each { |w| w.capitalize! }. # => %w(User Agent)
join('-') # => "User-Agent"
class Headers < HeaderHash
# symbol -> string mapper + cache
KeyMap = Hash.new do |map, key|
map[key] = if key.respond_to?(:to_str) then key
else
key.to_s.split('_'). # :user_agent => %w(user agent)
each { |w| w.capitalize! }. # => %w(User Agent)
join('-') # => "User-Agent"
end
end
KeyMap[:etag] = "ETag"
def [](k)
super(KeyMap[k])
end
def []=(k, v)
super(KeyMap[k], v)
end
alias_method :update, :merge!
def parse(header_string)
return unless header_string && !header_string.empty?
header_string.split(/\r\n/).
tap { |a| a.shift if a.first.index('HTTP/') == 0 }. # drop the HTTP status line
map { |h| h.split(/:\s+/, 2) }.reject { |(k, v)| k.nil? }. # split key and value, ignore blank lines
each { |(k, v)| self[k] = v }
end
end
HEADERS.merge! :etag => "ETag"
HEADERS.values.each { |v| v.freeze }
# Make Rack::Utils build_query method public.
public :build_query
@ -54,15 +72,10 @@ module Faraday
end
end
# Turns headers keys and values into strings. Look up symbol keys in the
# the HEADERS hash.
#
# h = merge_headers(HeaderHash.new, :content_type => 'text/plain')
# h['Content-Type'] # = 'text/plain'
#
# Turns headers keys and values into strings
def merge_headers(existing_headers, new_headers)
new_headers.each do |key, value|
existing_headers[HEADERS[key]] = value.to_s
existing_headers[key] = value.to_s
end
end

View File

@ -26,7 +26,9 @@ else
end
define_method "test_#{adapter}_GET_retrieves_the_response_headers" do
assert_match /text\/html/, create_connection(adapter).get('hello_world').headers['content-type']
response = create_connection(adapter).get('hello_world')
assert_match /text\/html/, response.headers['Content-Type'], 'original case fail'
assert_match /text\/html/, response.headers['content-type'], 'lowercase fail'
end
define_method "test_#{adapter}_POST_send_url_encoded_params" do

View File

@ -1,33 +0,0 @@
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'helper'))
if !Faraday::Adapter::Typhoeus.loaded?
warn "warning: Typhoeus failed to load; skipping tests for Typhoeus adapter"
else
module Adapters
class TestTyphoeus < Faraday::TestCase
def setup
@adapter = Faraday::Adapter::Typhoeus.new
end
def test_parse_response_headers_leaves_http_status_line_out
headers = @adapter.parse_response_headers("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n")
assert_equal %w(content-type), headers.keys
end
def test_parse_response_headers_parses_lower_cased_header_name_and_value
headers = @adapter.parse_response_headers("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n")
assert_equal 'text/html', headers['content-type']
end
def test_parse_response_headers_parses_lower_cased_header_name_and_value_with_colon
headers = @adapter.parse_response_headers("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nLocation: http://sushi.com/\r\n\r\n")
assert_equal 'http://sushi.com/', headers['location']
end
def test_parse_response_headers_parses_blank_lines
headers = @adapter.parse_response_headers("HTTP/1.1 200 OK\r\n\r\nContent-Type: text/html\r\n\r\n")
assert_equal 'text/html', headers['content-type']
end
end
end
end

View File

@ -1,15 +1,13 @@
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
class TestEnv < Faraday::TestCase
class EnvTest < Faraday::TestCase
def setup
@conn = Faraday.new :url => 'http://sushi.com/api', :headers => {'Mime-Version' => '1.0'}
@conn.options[:timeout] = 3
@conn.options[:open_timeout] = 5
@conn.ssl[:verify] = false
@conn.proxy 'http://proxy.com'
@input = {
:body => 'abc',
:headers => {'Server' => 'Faraday'}}
@input = { :body => 'abc' }
@env = env_for @conn do |req|
req.url 'foo.json', 'a' => 1
req['Server'] = 'Faraday'
@ -26,8 +24,15 @@ class TestEnv < Faraday::TestCase
end
def test_request_create_stores_headers
assert_kind_of Rack::Utils::HeaderHash, @env[:request_headers]
assert_equal @input[:headers].merge('Mime-Version' => '1.0'), @env[:request_headers]
headers = @env[:request_headers]
assert_equal '1.0', headers['mime-version']
assert_equal 'Faraday', headers['server']
end
def test_response_headers_case_insensitive
headers = @env[:response_headers]
headers['Content-Type'] = 'application/json'
assert_equal 'application/json', headers['content-type']
end
def test_request_create_stores_body
@ -54,3 +59,29 @@ class TestEnv < Faraday::TestCase
env_setup.to_env_hash(connection, :get)
end
end
class HeadersTest < Faraday::TestCase
def setup
@headers = Faraday::Utils::Headers.new
end
def test_parse_response_headers_leaves_http_status_line_out
@headers.parse("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n")
assert_equal %w(Content-Type), @headers.keys
end
def test_parse_response_headers_parses_lower_cased_header_name_and_value
@headers.parse("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n")
assert_equal 'text/html', @headers['content-type']
end
def test_parse_response_headers_parses_lower_cased_header_name_and_value_with_colon
@headers.parse("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nLocation: http://sushi.com/\r\n\r\n")
assert_equal 'http://sushi.com/', @headers['location']
end
def test_parse_response_headers_parses_blank_lines
@headers.parse("HTTP/1.1 200 OK\r\n\r\nContent-Type: text/html\r\n\r\n")
assert_equal 'text/html', @headers['content-type']
end
end