Skip to content

Commit

Permalink
Separate Request and Response bodies (#847)
Browse files Browse the repository at this point in the history
  • Loading branch information
iMacTia committed Feb 20, 2019
1 parent 6e4a2aa commit 6e3c40f
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 24 deletions.
4 changes: 4 additions & 0 deletions UPGRADING.md
Expand Up @@ -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+
Expand Down
18 changes: 16 additions & 2 deletions lib/faraday/options/env.rb
Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand All @@ -86,13 +87,26 @@ 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
custom_members[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)
Expand Down
14 changes: 8 additions & 6 deletions lib/faraday/response.rb
Expand Up @@ -31,8 +31,6 @@ def initialize(env = nil)

attr_reader :env

def_delegators :env, :to_hash

def status
finished? ? env.status : nil
end
Expand Down Expand Up @@ -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)
Expand Down
59 changes: 45 additions & 14 deletions 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
Expand All @@ -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
1 change: 0 additions & 1 deletion spec/faraday/response_spec.rb
Expand Up @@ -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) }
Expand Down
1 change: 0 additions & 1 deletion spec/support/shared_examples/request_method.rb
Expand Up @@ -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
Expand Down

0 comments on commit 6e3c40f

Please sign in to comment.