Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract configurations into separate object #939

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
198 changes: 32 additions & 166 deletions lib/stripe.rb
Expand Up @@ -12,6 +12,7 @@
require "set"
require "socket"
require "uri"
require "forwardable"

# Version
require "stripe/version"
Expand All @@ -38,6 +39,7 @@
require "stripe/api_resource"
require "stripe/singleton_api_resource"
require "stripe/webhook"
require "stripe/stripe_configuration"

# Named API resources
require "stripe/resources"
Expand All @@ -48,47 +50,41 @@
module Stripe
DEFAULT_CA_BUNDLE_PATH = __dir__ + "/data/ca-certificates.crt"

@app_info = nil

@api_base = "https://api.stripe.com"
@connect_base = "https://connect.stripe.com"
@uploads_base = "https://files.stripe.com"

@log_level = nil
@logger = nil

@proxy = nil

@max_network_retries = 0
@max_network_retry_delay = 2
@initial_network_retry_delay = 0.5

@ca_bundle_path = DEFAULT_CA_BUNDLE_PATH
@ca_store = nil
@verify_ssl_certs = true
# map to the same values as the standard library's logger
LEVEL_DEBUG = Logger::DEBUG
LEVEL_ERROR = Logger::ERROR
LEVEL_INFO = Logger::INFO
Comment on lines +53 to +56
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left the CA and LEVEL constants here in case folks reference them from outside the gem.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call.


@open_timeout = 30
@read_timeout = 80
@app_info = nil

@enable_telemetry = true
@configuration = Stripe::StripeConfiguration.setup
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could probably expose this if there's ever a desire to permit something like:

Stripe.configure do |config|
  # config.read_timeout = 100
end

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! Let's expose it separately if we decided to do so, but I think this configuration style would be much more "Ruby-ish" than what the gem currently offers.


class << self
attr_accessor :api_key
attr_accessor :api_version
extend Forwardable

# User configurable options
def_delegators :@configuration, :api_key, :api_key=
def_delegators :@configuration, :api_version, :api_version=
def_delegators :@configuration, :stripe_account, :stripe_account=
def_delegators :@configuration, :api_base, :api_base=
def_delegators :@configuration, :uploads_base, :uploads_base=
def_delegators :@configuration, :connect_base, :connect_base=
def_delegators :@configuration, :open_timeout, :open_timeout=
def_delegators :@configuration, :read_timeout, :read_timeout=
def_delegators :@configuration, :proxy, :proxy=
def_delegators :@configuration, :verify_ssl_certs, :verify_ssl_certs=
def_delegators :@configuration, :ca_bundle_path, :ca_bundle_path=
def_delegators :@configuration, :log_level, :log_level=
def_delegators :@configuration, :logger, :logger=
def_delegators :@configuration, :max_network_retries, :max_network_retries=
def_delegators :@configuration, :enable_telemetry=, :enable_telemetry?

# Internal configurations
def_delegators :@configuration, :max_network_retry_delay
def_delegators :@configuration, :initial_network_retry_delay
def_delegators :@configuration, :ca_store

attr_accessor :client_id
attr_accessor :stripe_account

# These all get manual attribute writers so that we can reset connections
# if they change.
attr_reader :api_base
attr_reader :connect_base
attr_reader :open_timeout
attr_reader :proxy
attr_reader :read_timeout
attr_reader :uploads_base
attr_reader :verify_ssl_certs

attr_reader :max_network_retry_delay, :initial_network_retry_delay
end

# Gets the application for a plugin that's identified some. See
Expand All @@ -101,126 +97,6 @@ def self.app_info=(info)
@app_info = info
end

def self.api_base=(api_base)
@api_base = api_base
StripeClient.clear_all_connection_managers
end

# The location of a file containing a bundle of CA certificates. By default
# the library will use an included bundle that can successfully validate
# Stripe certificates.
def self.ca_bundle_path
@ca_bundle_path
end

def self.ca_bundle_path=(path)
@ca_bundle_path = path

# empty this field so a new store is initialized
@ca_store = nil

StripeClient.clear_all_connection_managers
end

# A certificate store initialized from the the bundle in #ca_bundle_path and
# which is used to validate TLS on every request.
#
# This was added to the give the gem "pseudo thread safety" in that it seems
# when initiating many parallel requests marshaling the certificate store is
# the most likely point of failure (see issue #382). Any program attempting
# to leverage this pseudo safety should make a call to this method (i.e.
# `Stripe.ca_store`) in their initialization code because it marshals lazily
# and is itself not thread safe.
def self.ca_store
@ca_store ||= begin
store = OpenSSL::X509::Store.new
store.add_file(ca_bundle_path)
store
end
end

def self.connect_base=(connect_base)
@connect_base = connect_base
StripeClient.clear_all_connection_managers
end

def self.enable_telemetry?
@enable_telemetry
end

def self.enable_telemetry=(val)
@enable_telemetry = val
end

# map to the same values as the standard library's logger
LEVEL_DEBUG = Logger::DEBUG
LEVEL_ERROR = Logger::ERROR
LEVEL_INFO = Logger::INFO

# When set prompts the library to log some extra information to $stdout and
# $stderr about what it's doing. For example, it'll produce information about
# requests, responses, and errors that are received. Valid log levels are
# `debug` and `info`, with `debug` being a little more verbose in places.
#
# Use of this configuration is only useful when `.logger` is _not_ set. When
# it is, the decision what levels to print is entirely deferred to the logger.
def self.log_level
@log_level
end

def self.log_level=(val)
# Backwards compatibility for values that we briefly allowed
if val == "debug"
val = LEVEL_DEBUG
elsif val == "info"
val = LEVEL_INFO
end

if !val.nil? && ![LEVEL_DEBUG, LEVEL_ERROR, LEVEL_INFO].include?(val)
raise ArgumentError,
"log_level should only be set to `nil`, `debug` or `info`"
end
@log_level = val
end

# Sets a logger to which logging output will be sent. The logger should
# support the same interface as the `Logger` class that's part of Ruby's
# standard library (hint, anything in `Rails.logger` will likely be
# suitable).
#
# If `.logger` is set, the value of `.log_level` is ignored. The decision on
# what levels to print is entirely deferred to the logger.
def self.logger
@logger
end

def self.logger=(val)
@logger = val
end

def self.max_network_retries
@max_network_retries
end

def self.max_network_retries=(val)
@max_network_retries = val.to_i
end

def self.open_timeout=(open_timeout)
@open_timeout = open_timeout
StripeClient.clear_all_connection_managers
end

def self.proxy=(proxy)
@proxy = proxy
StripeClient.clear_all_connection_managers
end

def self.read_timeout=(read_timeout)
@read_timeout = read_timeout
StripeClient.clear_all_connection_managers
end

# Sets some basic information about the running application that's sent along
# with API requests. Useful for plugin authors to identify their plugin when
# communicating with Stripe.
Expand All @@ -234,16 +110,6 @@ def self.set_app_info(name, partner_id: nil, url: nil, version: nil)
version: version,
}
end

def self.uploads_base=(uploads_base)
@uploads_base = uploads_base
StripeClient.clear_all_connection_managers
end

def self.verify_ssl_certs=(verify_ssl_certs)
@verify_ssl_certs = verify_ssl_certs
StripeClient.clear_all_connection_managers
end
end

Stripe.log_level = ENV["STRIPE_LOG"] unless ENV["STRIPE_LOG"].nil?