From 7b660cea6529af19c40d05a39fd1e8a50beaa71a Mon Sep 17 00:00:00 2001 From: Chris Barton Date: Thu, 21 Oct 2021 18:34:26 -0700 Subject: [PATCH] Allow API base url configuration Adds the `base_url` and `ca_file` client configuration options which will be used as the base url when connecting to the API. Defaults to `https://v3.recurly.com` and the bundled ca file in the repo. --- lib/recurly/client.rb | 14 ++++++++++---- lib/recurly/connection_pool.rb | 20 +++++++++++--------- spec/recurly/client_spec.rb | 4 +++- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/lib/recurly/client.rb b/lib/recurly/client.rb index 16a7b3690..27a182415 100644 --- a/lib/recurly/client.rb +++ b/lib/recurly/client.rb @@ -3,6 +3,7 @@ require "net/https" require "base64" require "securerandom" +require "uri" require_relative "./schema/json_parser" require_relative "./schema/file_parser" @@ -10,8 +11,7 @@ module Recurly class Client require_relative "./client/operations" - BASE_HOST = "v3.recurly.com" - BASE_PORT = 443 + BASE_URL = "https://v3.recurly.com" CA_FILE = File.join(File.dirname(__FILE__), "../data/ca-certificates.crt") BINARY_TYPES = [ "application/pdf", @@ -54,10 +54,11 @@ class Client # # @param api_key [String] The private API key # @param logger [Logger] A logger to use. Defaults to creating a new STDOUT logger with level WARN. - def initialize(api_key:, logger: nil) + def initialize(base_url: BASE_URL, ca_file: CA_FILE, api_key:, logger: nil) raise ArgumentError, "'api_key' must be set to a non-nil value" if api_key.nil? set_api_key(api_key) + set_connection_options(base_url, ca_file) if logger.nil? @logger = Logger.new(STDOUT).tap do |l| @@ -158,7 +159,7 @@ class << self end def run_request(request, options = {}) - self.class.connection_pool.with_connection do |http| + self.class.connection_pool.with_connection(uri: @base_uri, ca_file: @ca_file) do |http| set_http_options(http, options) retries = 0 @@ -338,6 +339,11 @@ def set_api_key(api_key) @api_key = api_key.to_s end + def set_connection_options(base_url, ca_file) + @base_uri = URI.parse(base_url) + @ca_file = ca_file + end + def build_url(path, options) path = scope_by_site(path, options) query_params = map_array_params(options.fetch(:params, {})) diff --git a/lib/recurly/connection_pool.rb b/lib/recurly/connection_pool.rb index 500cf782d..eae4242f7 100644 --- a/lib/recurly/connection_pool.rb +++ b/lib/recurly/connection_pool.rb @@ -1,36 +1,38 @@ +# frozen_string_literal: true + require "net/https" module Recurly class ConnectionPool def initialize @mutex = Mutex.new - @pool = [] + @pool = Hash.new { |h, k| h[k] = [] } end - def with_connection + def with_connection(uri:, ca_file: nil) http = nil @mutex.synchronize do - http = @pool.pop + http = @pool[[uri.host, uri.port]].pop end # create connection if the pool was empty - http ||= init_http_connection + http ||= init_http_connection(uri, ca_file) response = yield http if http.started? @mutex.synchronize do - @pool.push(http) + @pool[[uri.host, uri.port]].push(http) end end response end - def init_http_connection - http = Net::HTTP.new(Client::BASE_HOST, Client::BASE_PORT) - http.use_ssl = true - http.ca_file = Client::CA_FILE + def init_http_connection(uri, ca_file) + http = Net::HTTP.new(uri.host, uri.port) + http.use_ssl = uri.scheme == "https" + http.ca_file = ca_file http.verify_mode = OpenSSL::SSL::VERIFY_PEER http.keep_alive_timeout = 600 diff --git a/spec/recurly/client_spec.rb b/spec/recurly/client_spec.rb index d219b1ab7..d9ae24bb3 100644 --- a/spec/recurly/client_spec.rb +++ b/spec/recurly/client_spec.rb @@ -17,7 +17,9 @@ "recurly-total-records" => "3804", } end - let(:net_http) { Recurly::ConnectionPool.new.init_http_connection } + let(:net_http) { + Recurly::ConnectionPool.new.init_http_connection(URI.parse(Recurly::Client::BASE_URL), Recurly::Client::CA_FILE) + } let(:connection_pool) { pool = double("ConnectionPool") allow(pool).to receive(:with_connection).and_yield net_http