diff --git a/lib/faraday.rb b/lib/faraday.rb index 92cb32301..687d70a4d 100644 --- a/lib/faraday.rb +++ b/lib/faraday.rb @@ -92,7 +92,7 @@ class << self # params: { page: 1 } # # => Faraday::Connection to http://faraday.com?page=1 def new(url = nil, options = {}, &block) - options = default_connection_options.merge(options) + options = Utils.deep_merge(default_connection_options, options) Faraday::Connection.new(url, options, &block) end diff --git a/lib/faraday/connection.rb b/lib/faraday/connection.rb index d97479628..20551a749 100644 --- a/lib/faraday/connection.rb +++ b/lib/faraday/connection.rb @@ -64,7 +64,7 @@ def initialize(url = nil, options = nil) options = ConnectionOptions.from(options) if url.is_a?(Hash) || url.is_a?(ConnectionOptions) - options = options.merge(url) + options = Utils.deep_merge(options, url) url = options.url end diff --git a/lib/faraday/utils.rb b/lib/faraday/utils.rb index a2be8b3be..428dc97ef 100644 --- a/lib/faraday/utils.rb +++ b/lib/faraday/utils.rb @@ -101,7 +101,7 @@ def normalize_path(url) # Recursive hash update def deep_merge!(target, hash) hash.each do |key, value| - target[key] = if value.is_a?(Hash) && target[key].is_a?(Hash) + target[key] = if value.is_a?(Hash) && (target[key].is_a?(Hash) || target[key].is_a?(Options)) deep_merge(target[key], value) else value diff --git a/spec/faraday/connection_spec.rb b/spec/faraday/connection_spec.rb index 3008ef4c0..932866be0 100644 --- a/spec/faraday/connection_spec.rb +++ b/spec/faraday/connection_spec.rb @@ -639,6 +639,24 @@ def decode(params) it_behaves_like 'default connection options' end + + context 'preserving a user_agent assigned via default_conncetion_options' do + context 'when url is a Hash' do + let(:conn) { Faraday.new(url: 'http://example.co', headers: { 'CustomHeader' => 'CustomValue' }) } + + before { Faraday.default_connection_options = { headers: { user_agent: 'My Agent 1.2' } } } + + it { expect(conn.headers).to eq('CustomHeader' => 'CustomValue', 'User-Agent' => 'My Agent 1.2') } + end + + context 'when url is a String' do + let(:conn) { Faraday.new('http://example.co', headers: { 'CustomHeader' => 'CustomValue' }) } + + before { Faraday.default_connection_options = { headers: { user_agent: 'My Agent 1.2' } } } + + it { expect(conn.headers).to eq('CustomHeader' => 'CustomValue', 'User-Agent' => 'My Agent 1.2') } + end + end end describe 'request params' do diff --git a/spec/faraday/utils_spec.rb b/spec/faraday/utils_spec.rb index 8bcf3f186..984ec589e 100644 --- a/spec/faraday/utils_spec.rb +++ b/spec/faraday/utils_spec.rb @@ -53,4 +53,65 @@ expect(headers).not_to have_key('authorization') end end + + describe '.deep_merge!' do + let(:connection_options) { Faraday::ConnectionOptions.new } + let(:url) do + { + url: 'http://example.com/abc', + headers: { 'Mime-Version' => '1.0' }, + request: { oauth: { consumer_key: 'anonymous' } }, + ssl: { version: '2' } + } + end + + it 'recursively merges the headers' do + connection_options.headers = { user_agent: 'My Agent 1.0' } + deep_merge = Faraday::Utils.deep_merge!(connection_options, url) + + expect(deep_merge.headers).to eq('Mime-Version' => '1.0', user_agent: 'My Agent 1.0') + end + + context 'when a target hash has an Options Struct value' do + let(:request) do + { + params_encoder: nil, + proxy: nil, + bind: nil, + timeout: nil, + open_timeout: nil, + read_timeout: nil, + write_timeout: nil, + boundary: nil, + oauth: { consumer_key: 'anonymous' }, + context: nil, + on_data: nil + } + end + let(:ssl) do + { + verify: nil, + ca_file: nil, + ca_path: nil, + verify_mode: nil, + cert_store: nil, + client_cert: nil, + client_key: nil, + certificate: nil, + private_key: nil, + verify_depth: nil, + version: '2', + min_version: nil, + max_version: nil + } + end + + it 'does not overwrite an Options Struct value' do + deep_merge = Faraday::Utils.deep_merge!(connection_options, url) + + expect(deep_merge.request.to_h).to eq(request) + expect(deep_merge.ssl.to_h).to eq(ssl) + end + end + end end