Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions lib/travel_time.rb
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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'
43 changes: 35 additions & 8 deletions lib/travel_time/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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

Expand Down
9 changes: 7 additions & 2 deletions lib/travel_time/middleware/authentication.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion lib/travel_time/middleware/proto.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
30 changes: 30 additions & 0 deletions spec/travel_time/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
Expand Down
3 changes: 2 additions & 1 deletion spec/travel_time/middleware/authentication_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion spec/travel_time/middleware/proto_middleware_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down