Skip to content

Commit

Permalink
Merge branch 'default-headers'
Browse files Browse the repository at this point in the history
  • Loading branch information
skuark committed Mar 16, 2020
2 parents a9d08de + 61c77e7 commit c966e8e
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 32 deletions.
32 changes: 16 additions & 16 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,42 @@ GEM
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.6.0)
public_suffix (>= 2.0.2, < 4.0)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
builder (3.2.3)
crack (0.4.3)
safe_yaml (~> 1.0.0)
diff-lcs (1.3)
hashdiff (1.0.0)
hashdiff (1.0.1)
httpclient (2.8.3)
i18n (0.8.1)
json (1.8.6)
mini_portile2 (2.4.0)
minitest (5.10.3)
nokogiri (1.10.8)
mini_portile2 (~> 2.4.0)
public_suffix (3.1.1)
public_suffix (4.0.3)
rake (13.0.1)
rdoc (4.1.1)
json (~> 1.4)
rspec (3.8.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-core (3.8.0)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.2)
rspec (3.9.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-core (3.9.1)
rspec-support (~> 3.9.1)
rspec-expectations (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.0)
rspec-support (~> 3.9.0)
rspec-mocks (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.0)
rspec-support (~> 3.9.0)
rspec-support (3.9.2)
safe_yaml (1.0.5)
thread_safe (0.3.6)
tzinfo (1.2.4)
thread_safe (~> 0.1)
webmock (3.6.2)
webmock (3.8.3)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
Expand Down
31 changes: 24 additions & 7 deletions lib/almodovar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,41 @@ module Almodovar
DEFAULT_RECEIVE_TIMEOUT = 120

class << self

# default_options allows to configure some settings on the underlying HTTP client used by Almodovar:
# - send_timeout: Request sending timeout in sec. Defaults to 120
# - connect_timeout: Connect timeout in sec. Defaults to 30
# - receive_timeout: Response receiving timeout in sec. Defaults to 120
# - user_agent: User-Agent header in HTTP request. defaults to Almodovar/#{Almodovar::VERSION}
# - force_basic_auth: flag for sending Authorization header w/o getting 401 first. Useful during tests
# - headers: is for providing default headers Hash that all HTTP
# requests should have, such as custom 'X-Request-Id' header in tracing.
# As Almodovar does not expose http API, this accept a proc which will be
# evaluated per request. You can override :headers with Almodovar::HTTPClient headers method
# or using Hash parameter in HTTP request methods but this is not accessible on default Almodovar usage.
def default_options
default = {
send_timeout: DEFAULT_SEND_TIMEOUT,
connect_timeout: DEFAULT_CONNECT_TIMEOUT,
receive_timeout: DEFAULT_RECEIVE_TIMEOUT,
user_agent: "Almodovar/#{Almodovar::VERSION}",
force_basic_auth: false
force_basic_auth: false,
headers: nil,
}
default.merge(@default_options || {})
end

def default_options=(options = {})
@default_options = {
send_timeout: options[:send_timeout],
connect_timeout: options[:connect_timeout],
receive_timeout: options[:receive_timeout],
force_basic_auth: options[:force_basic_auth]
}
@default_options ||= {}
# Only assign provided keys too keep defaults when merging
%i(send_timeout connect_timeout receive_timeout force_basic_auth headers).each do |key|
@default_options[key] = options[key] if options.has_key?(key)
end
@default_options
end

def reset_options
@default_options = nil
end
end
end
11 changes: 9 additions & 2 deletions lib/almodovar/http_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,15 @@ def delete(uri, query = {}, headers = {})

private

def merge_headers(headers)
(self.headers ||= {}).merge(headers)
def merge_headers(req_headers)
(default_headers || {}).
merge(self.headers ||= {}).
merge(req_headers)
end

def default_headers
defaults = Almodovar::default_options[:headers] || {}
defaults = defaults.is_a?(Proc) ? defaults.call() : defaults
end

def requires_auth?
Expand Down
11 changes: 4 additions & 7 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,13 @@ def auth
RSpec.configure do |config|
config.include Helpers
config.include WebMock::API
config.before(:suite) do
$default_options = Almodovar.default_options.dup
config.before(:each) do
Almodovar.reset_options
WebMock.reset!
end
config.before(:each) do |example|
unless example.metadata[:skip_force_basic_auth]
Almodovar.default_options = $default_options.merge(force_basic_auth: true)
Almodovar.default_options = { force_basic_auth: true }
end
end
config.after(:each) do
WebMock.reset!
Almodovar.default_options = $default_options
end
end
18 changes: 18 additions & 0 deletions spec/unit/default_options_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,23 @@

expect(Almodovar.default_options[:user_agent]).to eq("Almodovar/#{Almodovar::VERSION}")
end

it "overrides just provided options" do
Almodovar.default_options = { force_basic_auth: true }

options = Almodovar.default_options
expect(options[:send_timeout]).to eq(Almodovar::DEFAULT_SEND_TIMEOUT)
expect(options[:connect_timeout]).to eq(Almodovar::DEFAULT_CONNECT_TIMEOUT)
expect(options[:receive_timeout]).to eq(Almodovar::DEFAULT_RECEIVE_TIMEOUT)
expect(options[:headers]).to eq(nil)

Almodovar.default_options = { send_timeout: 10, headers: { 'Host' => 'movida.example.com' } }

options = Almodovar.default_options
expect(options[:send_timeout]).to eq(10)
expect(options[:connect_timeout]).to eq(Almodovar::DEFAULT_CONNECT_TIMEOUT)
expect(options[:receive_timeout]).to eq(Almodovar::DEFAULT_RECEIVE_TIMEOUT)
expect(options[:headers]).to eq({ 'Host' => 'movida.example.com' })
end
end
end
42 changes: 42 additions & 0 deletions spec/unit/http_client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,48 @@
expect(a_request(:get, "http://www.bebanjo.com").with(headers: {'Foo' => 'Bar', 'Baz' => 'Oink'})).to have_been_made
end

it "merges default headers with request headers" do
stub_request(:get, "http://www.bebanjo.com/")

default_headers = {'Foo' => 'Bar', 'Baz' => 'Bas'}
allow(Almodovar).to receive(:default_options).and_return(headers: default_headers)

client = Almodovar::HttpClient.new
client.get("http://www.bebanjo.com", {}, {'Baz' => 'Oink'})

expect(a_request(:get, "http://www.bebanjo.com").with(headers: {'Foo' => 'Bar', 'Baz' => 'Oink'})).to have_been_made
end

it "merges default headers with session headers with request headers" do
stub_request(:get, "http://www.bebanjo.com/")

default_headers = {'Chaflan' => 'Wadus', 'Foo' => 'Bing'}
allow(Almodovar).to receive(:default_options).and_return(headers: default_headers)

client = Almodovar::HttpClient.new.tap do |client|
client.headers = {'Foo' => 'Bar', 'Baz' => 'Bas'}
end

client.get("http://www.bebanjo.com", {}, {'Baz' => 'Oink'})

expect(a_request(:get, "http://www.bebanjo.com").with(headers: {'Chaflan' => 'Wadus', 'Foo' => 'Bar', 'Baz' => 'Oink'})).to have_been_made
end

it "evaluates default headers per request" do
stub_request(:get, "http://www.bebanjo.com/")

counter = 0
default_headers = Proc.new { { 'X-Counter' => (counter += 1) } }
allow(Almodovar).to receive(:default_options).and_return(headers: default_headers)

client = Almodovar::HttpClient.new
client.get("http://www.bebanjo.com")
expect(a_request(:get, "http://www.bebanjo.com").with(headers: {'X-Counter' => 1})).to have_been_made

client.get("http://www.bebanjo.com")
expect(a_request(:get, "http://www.bebanjo.com").with(headers: {'X-Counter' => 2})).to have_been_made
end

it "allows URI escaped characters in password" do
stub_request(:get, "http://www.bebanjo.com/")

Expand Down

0 comments on commit c966e8e

Please sign in to comment.