Skip to content

Commit 6e39505

Browse files
Import global configuration for options not available on StripeClient options (#1512)
* Fix client options not importing global config * update tests and fix bugs * lint * catch NotImplementedError and map for older Ruby * rubocop todo
1 parent 36b1c7c commit 6e39505

5 files changed

+119
-3
lines changed

lib/stripe.rb

+22
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,28 @@ module Stripe
7474
DEFAULT_UPLOAD_BASE = "https://files.stripe.com"
7575
DEFAULT_METER_EVENTS_BASE = "https://meter-events.stripe.com"
7676

77+
# Options that can be configured globally by users
78+
USER_CONFIGURABLE_GLOBAL_OPTIONS = Set.new(%i[
79+
api_key
80+
api_version
81+
stripe_account
82+
api_base
83+
uploads_base
84+
connect_base
85+
meter_events_base
86+
open_timeout
87+
read_timeout
88+
write_timeout
89+
proxy
90+
verify_ssl_certs
91+
ca_bundle_path
92+
log_level
93+
logger
94+
max_network_retries
95+
enable_telemetry
96+
client_id
97+
])
98+
7799
@app_info = nil
78100

79101
@config = Stripe::StripeConfiguration.setup

lib/stripe/stripe_client.rb

+6-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ class StripeClient
1010

1111
# attr_readers: The end of the section generated from our OpenAPI spec
1212

13+
# For internal use only. Does not provide a stable API and may be broken
14+
# with future non-major changes.
15+
CLIENT_OPTIONS = Set.new(%i[api_key stripe_account stripe_context api_version api_base uploads_base connect_base meter_events_base client_id])
16+
1317
# Initializes a new StripeClient
1418
def initialize(api_key, # rubocop:todo Metrics/ParameterLists
1519
stripe_account: nil,
@@ -40,7 +44,8 @@ def initialize(api_key, # rubocop:todo Metrics/ParameterLists
4044
client_id: client_id,
4145
}.reject { |_k, v| v.nil? }
4246

43-
@requestor = APIRequestor.new(config_opts)
47+
config = StripeConfiguration.client_init(config_opts)
48+
@requestor = APIRequestor.new(config)
4449

4550
# top-level services: The beginning of the section generated from our OpenAPI spec
4651
@v1 = Stripe::V1Services.new(@requestor)

lib/stripe/stripe_configuration.rb

+21-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,25 @@ def self.setup
3737
end
3838
end
3939

40+
# Set options to the StripeClient configured options, if valid as a client option and provided
41+
# Otherwise, for user configurable global options, set them to the global configuration
42+
# For all other options, set them to the StripeConfiguration default value
43+
def self.client_init(config_opts)
44+
global_config = Stripe.config
45+
imported_options = USER_CONFIGURABLE_GLOBAL_OPTIONS - StripeClient::CLIENT_OPTIONS
46+
client_config = StripeConfiguration.setup do |instance|
47+
imported_options.each do |key|
48+
begin
49+
instance.public_send("#{key}=", global_config.public_send(key)) if global_config.respond_to?(key)
50+
rescue NotImplementedError => e
51+
# In Ruby <= 2.5, we can't set write_timeout on Net::HTTP, log an error and continue
52+
Util.log_error("Failed to set #{key} on client configuration: #{e}")
53+
end
54+
end
55+
end
56+
client_config.reverse_duplicate_merge(config_opts)
57+
end
58+
4059
# Create a new config based off an existing one. This is useful when the
4160
# caller wants to override the global configuration
4261
def reverse_duplicate_merge(hash)
@@ -68,7 +87,8 @@ def initialize
6887
@connect_base = DEFAULT_CONNECT_BASE
6988
@uploads_base = DEFAULT_UPLOAD_BASE
7089
@meter_events_base = DEFAULT_METER_EVENTS_BASE
71-
@base_addresses = { api: @api_base, connect: @connect_base, files: @uploads_base, events: @meter_events_base }
90+
@base_addresses = { api: @api_base, connect: @connect_base, files: @uploads_base,
91+
meter_events: @meter_events_base, }
7292
end
7393

7494
def log_level=(val)

test/stripe/stripe_client_test.rb

+26-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class StripeClientTest < Test::Unit::TestCase
2020
@orig_api_key = Stripe.api_key
2121
@orig_stripe_account = Stripe.stripe_account
2222
@orig_open_timeout = Stripe.open_timeout
23+
@orig_api_version = Stripe.api_version
2324

2425
Stripe.api_key = "DONT_USE_THIS_KEY"
2526
Stripe.stripe_account = "DONT_USE_THIS_ACCOUNT"
@@ -30,6 +31,7 @@ class StripeClientTest < Test::Unit::TestCase
3031
Stripe.api_key = @orig_api_key
3132
Stripe.stripe_account = @orig_stripe_account
3233
Stripe.open_timeout = @orig_open_timeout
34+
Stripe.api_version = @orig_api_version
3335
end
3436

3537
should "use default config options" do
@@ -45,7 +47,6 @@ class StripeClientTest < Test::Unit::TestCase
4547
client = StripeClient.new("test_123")
4648
assert_equal "test_123", client.instance_variable_get(:@requestor).config.api_key
4749
assert_nil client.instance_variable_get(:@requestor).config.stripe_account
48-
assert_equal 30, client.instance_variable_get(:@requestor).config.open_timeout
4950
end
5051

5152
should "use client config options" do
@@ -67,6 +68,30 @@ class StripeClientTest < Test::Unit::TestCase
6768
assert_equal "2022-11-15", req.headers["Stripe-Version"]
6869
end
6970

71+
should "use global config options for options unavailable in client" do
72+
Stripe.api_key = "NOT_THIS_KEY"
73+
Stripe.stripe_account = "NOT_THIS_ACCOUNT"
74+
Stripe.api_version = "2022-11-15"
75+
client = StripeClient.new("test_123", stripe_account: "acct_123")
76+
# Imported from global options
77+
assert_equal 30_000, client.instance_variable_get(:@requestor).config.open_timeout
78+
# Not set in client options, not imported from global
79+
assert_equal client.instance_variable_get(:@requestor).config.api_base, Stripe::DEFAULT_API_BASE
80+
assert_equal client.instance_variable_get(:@requestor).config.api_version, Stripe::ApiVersion::CURRENT
81+
82+
req = nil
83+
stub_request(:get, "#{Stripe::DEFAULT_API_BASE}/v1/customers/cus_123")
84+
.with { |request| req = request }
85+
.to_return(body: JSON.generate(object: "customer"))
86+
87+
client.v1.customers.retrieve("cus_123")
88+
89+
# Set in client options
90+
assert_equal "Bearer test_123", req.headers["Authorization"]
91+
assert_equal "acct_123", req.headers["Stripe-Account"]
92+
assert_requested(:get, "#{Stripe::DEFAULT_API_BASE}/v1/customers/cus_123")
93+
end
94+
7095
should "request options overrides client config options" do
7196
client = StripeClient.new("test_123", stripe_version: "2022-11-15", stripe_account: "acct_123")
7297

test/stripe/stripe_configuration_test.rb

+44
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,50 @@ class StripeConfigurationTest < Test::Unit::TestCase
9797
end
9898
end
9999

100+
context "client_init" do
101+
setup do
102+
@client_opts = Hash[StripeClient::CLIENT_OPTIONS.map { |k| [k, nil] }] # rubocop:todo Style/HashConversion - necessary for Ruby <= 2.5
103+
@old_api_key = Stripe.api_key
104+
@old_stripe_account = Stripe.stripe_account
105+
@old_enable_telemetry = Stripe.instance_variable_get(:@enable_telemetry)
106+
@old_open_timeout = Stripe.open_timeout
107+
@old_uploads_base = Stripe.uploads_base
108+
end
109+
110+
teardown do
111+
Stripe.api_key = @old_api_key
112+
Stripe.stripe_account = @old_stripe_account
113+
Stripe.enable_telemetry = @old_enable_telemetry
114+
Stripe.open_timeout = @old_open_timeout
115+
Stripe.uploads_base = @old_uploads_base
116+
end
117+
118+
should "correctly set options for the client" do
119+
# mix of default, global, client options
120+
Stripe.api_key = "global_test_123"
121+
Stripe.stripe_account = "global_acct_123"
122+
Stripe.enable_telemetry = false
123+
Stripe.open_timeout = 30_000
124+
Stripe.uploads_base = "global_uploads_base.stripe.com"
125+
126+
@client_opts[:api_key] = "client_test_123"
127+
@client_opts[:stripe_account] = "client_acct_123"
128+
@client_opts[:uploads_base] = "client_uploads_base.stripe.com"
129+
@client_opts.reject! { |_k, v| v.nil? }
130+
131+
client_config = Stripe::StripeConfiguration.client_init(@client_opts)
132+
133+
assert_equal("client_test_123", client_config.api_key) # client api key
134+
assert_equal("client_acct_123", client_config.stripe_account) # client stripe account
135+
assert_equal(false, client_config.enable_telemetry) # global telemetry
136+
assert_equal(30_000, client_config.open_timeout) # global timeout
137+
assert_equal("client_uploads_base.stripe.com", client_config.base_addresses[:files]) # client uploads base
138+
assert_equal(Stripe::DEFAULT_API_BASE, client_config.base_addresses[:api]) # default api base
139+
assert_equal(ApiVersion::CURRENT, client_config.api_version) # default api version
140+
assert_equal(Stripe::DEFAULT_CA_BUNDLE_PATH, client_config.ca_bundle_path) # default ca bundle path
141+
end
142+
end
143+
100144
context "#max_network_retries=" do
101145
should "coerce the option into an integer" do
102146
config = Stripe::StripeConfiguration.setup

0 commit comments

Comments
 (0)