Adds reason phrase support (#547)

* Adds a `#reason_phrase` method to the Response class
Implements the reason phrase for the Net::Http adapter ONLY

* Reason phrase support for the Excon adapter

This assumes that the reason phrase is also implemented into the
Excon project

* Implement reason phrase for patron, httpclient, em_http, em_synchrony adapters.

* Don't test for reason phrase with Rack adapter, which doesn't make it available.

* Don't test for reason phrase support in Typhoeus adapter.

* Make reason_phrase nil in adapters that don't support it (instead of "")
This commit is contained in:
Leon Miller-Out 2016-08-24 12:43:19 -04:00 committed by Mattia
parent 05293e1950
commit a38ba7a13b
12 changed files with 40 additions and 8 deletions

View File

@ -34,9 +34,10 @@ module Faraday
env.clear_body if env.needs_body?
end
def save_response(env, status, body, headers = nil)
def save_response(env, status, body, headers = nil, reason_phrase = nil)
env.status = status
env.body = body
env.reason_phrase = reason_phrase && reason_phrase.to_s.strip
env.response_headers = Utils::Headers.new.tap do |response_headers|
response_headers.update headers unless headers.nil?
yield(response_headers) if block_given?

View File

@ -140,7 +140,9 @@ module Faraday
def perform_single_request(env)
req = EventMachine::HttpRequest.new(env[:url], connection_config(env))
req.setup_request(env[:method], request_config(env)).callback { |client|
save_response(env, client.response_header.status, client.response) do |resp_headers|
status = client.response_header.status
reason = client.response_header.http_reason
save_response(env, status, client.response, nil, reason) do |resp_headers|
client.response_header.each do |name, value|
resp_headers[name.to_sym] = value
end

View File

@ -54,7 +54,9 @@ module Faraday
raise client.error if client.error
save_response(env, client.response_header.status, client.response) do |resp_headers|
status = client.response_header.status
reason = client.response_header.http_reason
save_response(env, status, client.response, nil, reason) do |resp_headers|
client.response_header.each do |name, value|
resp_headers[name.to_sym] = value
end

View File

@ -57,7 +57,7 @@ module Faraday
:headers => env[:request_headers],
:body => read_body(env)
save_response(env, resp.status.to_i, resp.body, resp.headers)
save_response(env, resp.status.to_i, resp.body, resp.headers, resp.reason_phrase)
@app.call env
rescue ::Excon::Errors::SocketError => err

View File

@ -37,7 +37,7 @@ module Faraday
:body => env[:body],
:header => env[:request_headers]
save_response env, resp.status, resp.body, resp.headers
save_response env, resp.status, resp.body, resp.headers, resp.reason
@app.call env
rescue ::HTTPClient::TimeoutError, Errno::ETIMEDOUT

View File

@ -46,7 +46,7 @@ module Faraday
end
end
save_response(env, http_response.code.to_i, http_response.body || '') do |response_headers|
save_response(env, http_response.code.to_i, http_response.body || '', nil, http_response.message) do |response_headers|
http_response.each_header do |key, value|
response_headers[key] = value
end

View File

@ -35,7 +35,10 @@ module Faraday
raise Error::ConnectionFailed, $!
end
save_response(env, response.status, response.body, response.headers)
# Remove the "HTTP/1.1 200", leaving just the reason phrase
reason_phrase = response.status_line.gsub(/^.* \d{3} /, '')
save_response(env, response.status, response.body, response.headers, reason_phrase)
@app.call env
rescue ::Patron::TimeoutError => err

View File

@ -252,7 +252,8 @@ module Faraday
end
class Env < Options.new(:method, :body, :url, :request, :request_headers,
:ssl, :parallel_manager, :params, :response, :response_headers, :status)
:ssl, :parallel_manager, :params, :response, :response_headers, :status,
:reason_phrase)
ContentLength = 'Content-Length'.freeze
StatusesWithoutBody = Set.new [204, 304]

View File

@ -37,6 +37,10 @@ module Faraday
finished? ? env.status : nil
end
def reason_phrase
finished? ? env.reason_phrase : nil
end
def headers
finished? ? env.response_headers : {}
end

View File

@ -114,6 +114,11 @@ module Adapters
assert_equal expected, get('ssl').body
end
def test_GET_reason_phrase
response = get('echo')
assert_equal "OK", response.reason_phrase
end
def test_POST_send_url_encoded_params
assert_equal %(post {"name"=>"zack"}), post('echo', :name => 'zack').body
end

View File

@ -14,6 +14,13 @@ module Adapters
include Integration::Common
include Integration::NonParallel
# Rack::MockResponse doesn't provide any way to access the reason phrase,
# so override the shared test from Common.
def test_GET_reason_phrase
response = get('echo')
assert_nil response.reason_phrase
end
# not using shared test because error is swallowed by Sinatra
def test_timeout
conn = create_connection(:request => {:timeout => 1, :open_timeout => 1})

View File

@ -16,6 +16,13 @@ module Adapters
# inconsistent outcomes ranging from successful response to connection error
undef :test_proxy_auth_fail if ssl_mode?
# Typhoeus::Response doesn't provide an easy way to access the reason phrase,
# so override the shared test from Common.
def test_GET_reason_phrase
response = get('echo')
assert_nil response.reason_phrase
end
def test_binds_local_socket
host = '1.2.3.4'
conn = create_connection :request => { :bind => { :host => host } }