diff --git a/lib/travel_time.rb b/lib/travel_time.rb index d9acc8e..9288e16 100644 --- a/lib/travel_time.rb +++ b/lib/travel_time.rb @@ -1,11 +1,6 @@ # frozen_string_literal: true require 'dry/configurable' -require 'travel_time/client' -require 'travel_time/error' -require 'travel_time/response' -require 'travel_time/version' -require 'utils' # Main TravelTime module module TravelTime @@ -20,3 +15,9 @@ module TravelTime setting :enable_logging, default: false setting :raise_on_failure, default: false end + +require 'travel_time/client' +require 'travel_time/error' +require 'travel_time/response' +require 'travel_time/version' +require 'utils' diff --git a/lib/travel_time/client.rb b/lib/travel_time/client.rb index cc6f7db..ac8ea82 100644 --- a/lib/travel_time/client.rb +++ b/lib/travel_time/client.rb @@ -9,10 +9,19 @@ module TravelTime # The Client class provides the main interface to interact with the TravelTime API class Client # rubocop:disable Metrics/ClassLength + include Dry::Configurable extend Limiter::Mixin API_BASE_URL = 'https://api.traveltimeapp.com/v4/' + TravelTime.settings.each do |s| + if s.default.nil? + setting s.name + else + setting s.name, default: s.default + end + end + attr_reader :connection, :proto_connection def initialize(rate_limit = nil) @@ -26,23 +35,41 @@ def initialize(rate_limit = nil) end end + # Override configure to reinitialize connections after config changes + def configure + super.tap do + init_connection + init_proto_connection + end + end + + def effective_config + has_instance_config = TravelTime.settings.any? do |s| + value = config.public_send(s.name) + s.default.nil? ? !value.nil? : value != s.default + end + has_instance_config ? config : TravelTime.config + end + def init_connection + cfg = effective_config @connection = Faraday.new(API_BASE_URL) do |f| f.request :json - f.response :raise_error if TravelTime.config.raise_on_failure - f.response :logger if TravelTime.config.enable_logging + f.response :raise_error if cfg.raise_on_failure + f.response :logger if cfg.enable_logging f.response :json - f.use TravelTime::Middleware::Authentication - f.adapter TravelTime.config.http_adapter || Faraday.default_adapter + f.use TravelTime::Middleware::Authentication, config: cfg + f.adapter cfg.http_adapter || Faraday.default_adapter end end def init_proto_connection + cfg = effective_config @proto_connection = Faraday.new do |f| - f.use TravelTime::Middleware::ProtoMiddleware - f.response :raise_error if TravelTime.config.raise_on_failure - f.response :logger if TravelTime.config.enable_logging - f.adapter TravelTime.config.http_adapter || Faraday.default_adapter + f.use TravelTime::Middleware::ProtoMiddleware, config: cfg + f.response :raise_error if cfg.raise_on_failure + f.response :logger if cfg.enable_logging + f.adapter cfg.http_adapter || Faraday.default_adapter end end diff --git a/lib/travel_time/middleware/authentication.rb b/lib/travel_time/middleware/authentication.rb index 1c5cf15..585cc01 100644 --- a/lib/travel_time/middleware/authentication.rb +++ b/lib/travel_time/middleware/authentication.rb @@ -11,9 +11,14 @@ class Authentication < Faraday::Middleware API_KEY_HEADER = 'X-Api-Key' USER_AGENT = 'User-Agent' + def initialize(app, options = {}) + super(app) + @config = options[:config] || TravelTime.config + end + def on_request(env) - env.request_headers[APP_ID_HEADER] = TravelTime.config.application_id - env.request_headers[API_KEY_HEADER] = TravelTime.config.api_key + env.request_headers[APP_ID_HEADER] = @config.application_id + env.request_headers[API_KEY_HEADER] = @config.api_key env.request_headers[USER_AGENT] = "Travel Time Ruby SDK #{TravelTime::VERSION}" end end diff --git a/lib/travel_time/middleware/proto.rb b/lib/travel_time/middleware/proto.rb index c524630..94daca2 100644 --- a/lib/travel_time/middleware/proto.rb +++ b/lib/travel_time/middleware/proto.rb @@ -8,9 +8,14 @@ module Middleware # The Proto middleware is responsible for setting the basic auth headers for proto requests # on each request. These are automatically taken from the `TravelTime.config`. class ProtoMiddleware < Faraday::Middleware + def initialize(app, options = {}) + super(app) + @config = options[:config] || TravelTime.config + end + def on_request(env) env.request_headers['Authorization'] = - "Basic #{Base64.encode64("#{TravelTime.config.application_id}:#{TravelTime.config.api_key}")}" + "Basic #{Base64.encode64("#{@config.application_id}:#{@config.api_key}")}" env.request_headers['Content-Type'] = 'application/octet-stream' env.request_headers['Accept'] = 'application/octet-stream' env.request_headers['User-Agent'] = 'Travel Time Ruby SDK' diff --git a/spec/travel_time/client_spec.rb b/spec/travel_time/client_spec.rb index 97a6753..b077f39 100644 --- a/spec/travel_time/client_spec.rb +++ b/spec/travel_time/client_spec.rb @@ -13,6 +13,36 @@ expect(connection.builder.handlers).to include(TravelTime::Middleware::Authentication) end + describe 'custom credentials' do + let(:custom_client) do + described_class.new.configure do |config| + config.application_id = 'CUSTOM_APP_ID' + config.api_key = 'CUSTOM_KEY' + end + end + + it 'allows setting custom application_id' do + expect(custom_client.config.application_id).to eq('CUSTOM_APP_ID') + end + + it 'allows setting custom api_key' do + expect(custom_client.config.api_key).to eq('CUSTOM_KEY') + end + + it 'uses instance config when custom credentials are set' do + custom_client = described_class.new.configure do |config| + config.application_id = 'CUSTOM_APP_ID' + config.api_key = 'CUSTOM_KEY' + end + expect(custom_client.send(:effective_config)).to eq(custom_client.config) + end + + it 'falls back to global config when no custom credentials are set' do + default_client = described_class.new + expect(default_client.send(:effective_config)).to eq(TravelTime.config) + end + end + describe 'connection adapter' do context 'with default config' do let(:expected) { Faraday::Adapter.lookup_middleware(Faraday.default_adapter) } diff --git a/spec/travel_time/middleware/authentication_spec.rb b/spec/travel_time/middleware/authentication_spec.rb index 666c783..2cd44d3 100644 --- a/spec/travel_time/middleware/authentication_spec.rb +++ b/spec/travel_time/middleware/authentication_spec.rb @@ -6,7 +6,8 @@ env.request_headers = Faraday::Utils::Headers.new end end - let(:middleware) { described_class.new } + let(:app) { instance_double(Faraday::Middleware) } + let(:middleware) { described_class.new(app) } it 'automatically fetches the application_id from the configuration and set it for the request' do middleware.on_request(faraday_env) diff --git a/spec/travel_time/middleware/proto_middleware_spec.rb b/spec/travel_time/middleware/proto_middleware_spec.rb index 29f24bb..b868b1f 100644 --- a/spec/travel_time/middleware/proto_middleware_spec.rb +++ b/spec/travel_time/middleware/proto_middleware_spec.rb @@ -6,7 +6,8 @@ env.request_headers = Faraday::Utils::Headers.new end end - let(:middleware) { described_class.new } + let(:app) { instance_double(Faraday::Middleware) } + let(:middleware) { described_class.new(app) } it 'adds basic auth header' do middleware.on_request(faraday_env)