diff --git a/UPGRADING.md b/UPGRADING.md index b745c5b9e..6bbd21c94 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -13,6 +13,10 @@ Please note `Faraday::ClientError` was previously used for both. * Faraday::ProxyAuthError (407). Please note this raised a `Faraday::ConnectionFailed` before. * Faraday::UnprocessableEntityError (422) +### Custom adapters +If you have written a custom adapter, please be aware that `env.body` is now an alias to the two new properties `request_body` and `response_body`. +This should work without you noticing if your adapter inherits from `Faraday::Adapter` and calls `save_response`, but if it doesn't, then please ensure you set the `status` BEFORE the `body` while processing the response. + ### Others * Dropped support for jruby and Rubinius. * Officially supports Ruby 2.3+ diff --git a/lib/faraday/options/env.rb b/lib/faraday/options/env.rb index 88146b299..dfa86c8a5 100644 --- a/lib/faraday/options/env.rb +++ b/lib/faraday/options/env.rb @@ -43,9 +43,9 @@ module Faraday # # @!attribute reason_phrase # @return [String] - class Env < Options.new(:method, :body, :url, :request, :request_headers, + class Env < Options.new(:method, :request_body, :url, :request, :request_headers, :ssl, :parallel_manager, :params, :response, :response_headers, :status, - :reason_phrase) + :reason_phrase, :response_body) ContentLength = 'Content-Length'.freeze StatusesWithoutBody = Set.new [204, 304] @@ -76,6 +76,7 @@ def self.from(value) # @param key [Object] def [](key) + return self[current_body] if key == :body if in_member_set?(key) super(key) else @@ -86,6 +87,7 @@ def [](key) # @param key [Object] # @param value [Object] def []=(key, value) + return super(current_body, value) if key == :body if in_member_set?(key) super(key, value) else @@ -93,6 +95,18 @@ def []=(key, value) end end + def current_body + !!status ? :response_body : :request_body + end + + def body + self[:body] + end + + def body=(value) + self[:body] = value + end + # @return [Boolean] true if status is in the set of {SuccessfulStatuses}. def success? SuccessfulStatuses.include?(status) diff --git a/lib/faraday/response.rb b/lib/faraday/response.rb index 4c2573f7b..50ccf8edb 100644 --- a/lib/faraday/response.rb +++ b/lib/faraday/response.rb @@ -31,8 +31,6 @@ def initialize(env = nil) attr_reader :env - def_delegators :env, :to_hash - def status finished? ? env.status : nil end @@ -74,12 +72,16 @@ def success? finished? && env.success? end + def to_hash + { + :status => env.status, :body => env.body, + :response_headers => env.response_headers + } + end + # because @on_complete_callbacks cannot be marshalled def marshal_dump - !finished? ? nil : { - :status => @env.status, :body => @env.body, - :response_headers => @env.response_headers - } + finished? ? to_hash : nil end def marshal_load(env) diff --git a/spec/faraday/options/env_spec.rb b/spec/faraday/options/env_spec.rb index 6ff52e07f..f8dca2497 100644 --- a/spec/faraday/options/env_spec.rb +++ b/spec/faraday/options/env_spec.rb @@ -1,21 +1,22 @@ RSpec.describe Faraday::Env do - subject { Faraday::Env.new } + subject(:env) { described_class.new } + it 'allows to access members' do - expect(subject.method).to be_nil - subject.method = :get - expect(subject.method).to eq(:get) + expect(env.method).to be_nil + env.method = :get + expect(env.method).to eq(:get) end it 'allows to access symbol non members' do - expect(subject[:custom]).to be_nil - subject[:custom] = :boom - expect(subject[:custom]).to eq(:boom) + expect(env[:custom]).to be_nil + env[:custom] = :boom + expect(env[:custom]).to eq(:boom) end it 'allows to access string non members' do - expect(subject['custom']).to be_nil - subject['custom'] = :boom - expect(subject['custom']).to eq(:boom) + expect(env['custom']).to be_nil + env['custom'] = :boom + expect(env['custom']).to eq(:boom) end it 'ignores false when fetching' do @@ -25,13 +26,43 @@ end it 'retains custom members' do - subject[:foo] = "custom 1" - subject[:bar] = :custom_2 - env2 = Faraday::Env.from(subject) + env[:foo] = "custom 1" + env[:bar] = :custom_2 + env2 = Faraday::Env.from(env) env2[:baz] = "custom 3" expect(env2[:foo]).to eq("custom 1") expect(env2[:bar]).to eq(:custom_2) - expect(subject[:baz]).to be_nil + expect(env[:baz]).to be_nil + end + + describe '#body' do + subject(:env) { described_class.from(body: { foo: 'bar' }) } + + context 'when response is not finished yet' do + it 'returns the request body' do + expect(env.body).to eq({ foo: 'bar' }) + end + end + + context 'when response is finished' do + before do + env.status = 200 + env.body = { bar: 'foo' } + env.response = Faraday::Response.new(env) + end + + it 'returns the response body' do + expect(env.body).to eq({ bar: 'foo' }) + end + + it 'allows to access request_body' do + expect(env.request_body).to eq({ foo: 'bar' }) + end + + it 'allows to access response_body' do + expect(env.response_body).to eq({ bar: 'foo' }) + end + end end end \ No newline at end of file diff --git a/spec/faraday/response_spec.rb b/spec/faraday/response_spec.rb index 805e9ea26..972fecb41 100644 --- a/spec/faraday/response_spec.rb +++ b/spec/faraday/response_spec.rb @@ -25,7 +25,6 @@ let(:hash) { subject.to_hash } it { expect(hash).to be_a(Hash) } - it { expect(hash).to eq(env.to_hash) } it { expect(hash[:status]).to eq(subject.status) } it { expect(hash[:response_headers]).to eq(subject.headers) } it { expect(hash[:body]).to eq(subject.body) } diff --git a/spec/support/shared_examples/request_method.rb b/spec/support/shared_examples/request_method.rb index 9687c9718..dafb23a3f 100644 --- a/spec/support/shared_examples/request_method.rb +++ b/spec/support/shared_examples/request_method.rb @@ -167,7 +167,6 @@ it 'handles requests with proxy' do conn_options[:proxy] = 'http://google.co.uk' - # binding.pry res = conn.public_send(http_method, '/') expect(res.status).to eq(200) end