Skip to content

Commit

Permalink
Adds reason phrase support (#547)
Browse files Browse the repository at this point in the history
* 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 "")
  • Loading branch information
sbleon authored and iMacTia committed Aug 24, 2016
1 parent 05293e1 commit a38ba7a
Show file tree
Hide file tree
Showing 12 changed files with 40 additions and 8 deletions.
3 changes: 2 additions & 1 deletion lib/faraday/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ def call(env)
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?
Expand Down
4 changes: 3 additions & 1 deletion lib/faraday/adapter/em_http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ def perform_request(env)
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
Expand Down
4 changes: 3 additions & 1 deletion lib/faraday/adapter/em_synchrony.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ def call(env)

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
Expand Down
2 changes: 1 addition & 1 deletion lib/faraday/adapter/excon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def call(env)
: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
Expand Down
2 changes: 1 addition & 1 deletion lib/faraday/adapter/httpclient.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def call(env)
: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
Expand Down
2 changes: 1 addition & 1 deletion lib/faraday/adapter/net_http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def call(env)
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
Expand Down
5 changes: 4 additions & 1 deletion lib/faraday/adapter/patron.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ def call(env)
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
Expand Down
3 changes: 2 additions & 1 deletion lib/faraday/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,8 @@ def new_builder(block)
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]
Expand Down
4 changes: 4 additions & 0 deletions lib/faraday/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ def status
finished? ? env.status : nil
end

def reason_phrase
finished? ? env.reason_phrase : nil
end

def headers
finished? ? env.response_headers : {}
end
Expand Down
5 changes: 5 additions & 0 deletions test/adapters/integration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ def test_GET_ssl
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
Expand Down
7 changes: 7 additions & 0 deletions test/adapters/rack_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ def adapter_options
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})
Expand Down
7 changes: 7 additions & 0 deletions test/adapters/typhoeus_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ def adapter() :typhoeus end
# 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 } }
Expand Down

0 comments on commit a38ba7a

Please sign in to comment.