stripe 5.30.0 → 5.31.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -101,14 +101,22 @@ module Stripe
101
101
  @max_network_retries = val.to_i
102
102
  end
103
103
 
104
+ def max_network_retry_delay=(val)
105
+ @max_network_retry_delay = val.to_i
106
+ end
107
+
108
+ def initial_network_retry_delay=(val)
109
+ @initial_network_retry_delay = val.to_i
110
+ end
111
+
104
112
  def open_timeout=(open_timeout)
105
113
  @open_timeout = open_timeout
106
- StripeClient.clear_all_connection_managers
114
+ StripeClient.clear_all_connection_managers(config: self)
107
115
  end
108
116
 
109
117
  def read_timeout=(read_timeout)
110
118
  @read_timeout = read_timeout
111
- StripeClient.clear_all_connection_managers
119
+ StripeClient.clear_all_connection_managers(config: self)
112
120
  end
113
121
 
114
122
  def write_timeout=(write_timeout)
@@ -117,32 +125,32 @@ module Stripe
117
125
  end
118
126
 
119
127
  @write_timeout = write_timeout
120
- StripeClient.clear_all_connection_managers
128
+ StripeClient.clear_all_connection_managers(config: self)
121
129
  end
122
130
 
123
131
  def proxy=(proxy)
124
132
  @proxy = proxy
125
- StripeClient.clear_all_connection_managers
133
+ StripeClient.clear_all_connection_managers(config: self)
126
134
  end
127
135
 
128
136
  def verify_ssl_certs=(verify_ssl_certs)
129
137
  @verify_ssl_certs = verify_ssl_certs
130
- StripeClient.clear_all_connection_managers
138
+ StripeClient.clear_all_connection_managers(config: self)
131
139
  end
132
140
 
133
141
  def uploads_base=(uploads_base)
134
142
  @uploads_base = uploads_base
135
- StripeClient.clear_all_connection_managers
143
+ StripeClient.clear_all_connection_managers(config: self)
136
144
  end
137
145
 
138
146
  def connect_base=(connect_base)
139
147
  @connect_base = connect_base
140
- StripeClient.clear_all_connection_managers
148
+ StripeClient.clear_all_connection_managers(config: self)
141
149
  end
142
150
 
143
151
  def api_base=(api_base)
144
152
  @api_base = api_base
145
- StripeClient.clear_all_connection_managers
153
+ StripeClient.clear_all_connection_managers(config: self)
146
154
  end
147
155
 
148
156
  def ca_bundle_path=(path)
@@ -151,7 +159,7 @@ module Stripe
151
159
  # empty this field so a new store is initialized
152
160
  @ca_store = nil
153
161
 
154
- StripeClient.clear_all_connection_managers
162
+ StripeClient.clear_all_connection_managers(config: self)
155
163
  end
156
164
 
157
165
  # A certificate store initialized from the the bundle in #ca_bundle_path and
@@ -174,5 +182,13 @@ module Stripe
174
182
  def enable_telemetry?
175
183
  enable_telemetry
176
184
  end
185
+
186
+ # Generates a deterministic key to identify configuration objects with
187
+ # identical configuration values.
188
+ def key
189
+ instance_variables
190
+ .collect { |variable| instance_variable_get(variable) }
191
+ .join
192
+ end
177
193
  end
178
194
  end
@@ -267,6 +267,27 @@ module Stripe
267
267
  []
268
268
  end
269
269
 
270
+ # When designing APIs, we now make a conscious effort server-side to avoid
271
+ # naming fields after important built-ins in various languages (e.g. class,
272
+ # method, etc.).
273
+ #
274
+ # However, a long time ago we made the mistake (either consciously or by
275
+ # accident) of initializing our `metadata` fields as instances of
276
+ # `StripeObject`, and metadata can have a wide range of different keys
277
+ # defined in it. This is somewhat a convenient in that it allows users to
278
+ # access data like `obj.metadata.my_field`, but is almost certainly not
279
+ # worth the cost.
280
+ #
281
+ # Naming metadata fields bad things like `class` causes `initialize_from`
282
+ # to produce strange results, so we ban known offenders here.
283
+ #
284
+ # In a future major version we should consider leaving `metadata` as a hash
285
+ # and forcing people to access it with `obj.metadata[:my_field]` because
286
+ # the potential for trouble is just too high. For now, reserve names.
287
+ RESERVED_FIELD_NAMES = [
288
+ :class,
289
+ ].freeze
290
+
270
291
  protected def metaclass
271
292
  class << self; self; end
272
293
  end
@@ -277,6 +298,7 @@ module Stripe
277
298
 
278
299
  metaclass.instance_eval do
279
300
  keys.each do |k|
301
+ next if RESERVED_FIELD_NAMES.include?(k)
280
302
  next if protected_fields.include?(k)
281
303
  next if @@permanent_attributes.include?(k)
282
304
 
@@ -312,6 +334,7 @@ module Stripe
312
334
 
313
335
  metaclass.instance_eval do
314
336
  keys.each do |k|
337
+ next if RESERVED_FIELD_NAMES.include?(k)
315
338
  next if protected_fields.include?(k)
316
339
  next if @@permanent_attributes.include?(k)
317
340
 
data/lib/stripe/util.rb CHANGED
@@ -76,24 +76,30 @@ module Stripe
76
76
  end
77
77
 
78
78
  def self.log_error(message, data = {})
79
- if !Stripe.logger.nil? ||
80
- !Stripe.log_level.nil? && Stripe.log_level <= Stripe::LEVEL_ERROR
79
+ config = data.delete(:config) || Stripe.config
80
+ logger = config.logger || Stripe.logger
81
+ if !logger.nil? ||
82
+ !config.log_level.nil? && config.log_level <= Stripe::LEVEL_ERROR
81
83
  log_internal(message, data, color: :cyan, level: Stripe::LEVEL_ERROR,
82
84
  logger: Stripe.logger, out: $stderr)
83
85
  end
84
86
  end
85
87
 
86
88
  def self.log_info(message, data = {})
87
- if !Stripe.logger.nil? ||
88
- !Stripe.log_level.nil? && Stripe.log_level <= Stripe::LEVEL_INFO
89
+ config = data.delete(:config) || Stripe.config
90
+ logger = config.logger || Stripe.logger
91
+ if !logger.nil? ||
92
+ !config.log_level.nil? && config.log_level <= Stripe::LEVEL_INFO
89
93
  log_internal(message, data, color: :cyan, level: Stripe::LEVEL_INFO,
90
94
  logger: Stripe.logger, out: $stdout)
91
95
  end
92
96
  end
93
97
 
94
98
  def self.log_debug(message, data = {})
95
- if !Stripe.logger.nil? ||
96
- !Stripe.log_level.nil? && Stripe.log_level <= Stripe::LEVEL_DEBUG
99
+ config = data.delete(:config) || Stripe.config
100
+ logger = config.logger || Stripe.logger
101
+ if !logger.nil? ||
102
+ !config.log_level.nil? && config.log_level <= Stripe::LEVEL_DEBUG
97
103
  log_internal(message, data, color: :blue, level: Stripe::LEVEL_DEBUG,
98
104
  logger: Stripe.logger, out: $stdout)
99
105
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Stripe
4
- VERSION = "5.30.0"
4
+ VERSION = "5.31.0"
5
5
  end
@@ -79,6 +79,49 @@ module Stripe
79
79
  end
80
80
  end
81
81
 
82
+ context "when a StripeClient has different configurations" do
83
+ should "correctly initialize a connection" do
84
+ old_proxy = Stripe.proxy
85
+
86
+ old_open_timeout = Stripe.open_timeout
87
+ old_read_timeout = Stripe.read_timeout
88
+
89
+ begin
90
+ client = StripeClient.new(
91
+ proxy: "http://other:pass@localhost:8080",
92
+ open_timeout: 400,
93
+ read_timeout: 500,
94
+ verify_ssl_certs: true
95
+ )
96
+ conn = Stripe::ConnectionManager.new(client.config)
97
+ .connection_for("https://stripe.com")
98
+
99
+ # Host/port
100
+ assert_equal "stripe.com", conn.address
101
+ assert_equal 443, conn.port
102
+
103
+ # Proxy
104
+ assert_equal "localhost", conn.proxy_address
105
+ assert_equal 8080, conn.proxy_port
106
+ assert_equal "other", conn.proxy_user
107
+ assert_equal "pass", conn.proxy_pass
108
+
109
+ # Timeouts
110
+ assert_equal 400, conn.open_timeout
111
+ assert_equal 500, conn.read_timeout
112
+
113
+ assert_equal true, conn.use_ssl?
114
+ assert_equal OpenSSL::SSL::VERIFY_PEER, conn.verify_mode
115
+ assert_equal Stripe.ca_store, conn.cert_store
116
+ ensure
117
+ Stripe.proxy = old_proxy
118
+
119
+ Stripe.open_timeout = old_open_timeout
120
+ Stripe.read_timeout = old_read_timeout
121
+ end
122
+ end
123
+ end
124
+
82
125
  should "produce the same connection multiple times" do
83
126
  conn1 = @manager.connection_for("https://stripe.com")
84
127
  conn2 = @manager.connection_for("https://stripe.com")
@@ -44,6 +44,14 @@ module Stripe
44
44
  assert_equal("connect.stripe.com", uri.host)
45
45
  assert_equal("/express/oauth/authorize", uri.path)
46
46
  end
47
+
48
+ should "override the api base path when a StripeClient is provided" do
49
+ client = Stripe::StripeClient.new(connect_base: "https://other.stripe.com")
50
+ uri_str = OAuth.authorize_url({}, client: client)
51
+
52
+ uri = URI.parse(uri_str)
53
+ assert_equal("other.stripe.com", uri.host)
54
+ end
47
55
  end
48
56
 
49
57
  context ".token" do
@@ -83,6 +91,29 @@ module Stripe
83
91
  code: "this_is_an_authorization_code")
84
92
  assert_equal("another_access_token", resp.access_token)
85
93
  end
94
+
95
+ should "override the api base path when a StripeClient is provided" do
96
+ stub_request(:post, "https://other.stripe.com/oauth/token")
97
+ .with(body: {
98
+ "grant_type" => "authorization_code",
99
+ "code" => "this_is_an_authorization_code",
100
+ })
101
+ .to_return(body: JSON.generate(access_token: "sk_access_token",
102
+ scope: "read_only",
103
+ livemode: false,
104
+ token_type: "bearer",
105
+ refresh_token: "sk_refresh_token",
106
+ stripe_user_id: "acct_test",
107
+ stripe_publishable_key: "pk_test"))
108
+
109
+ client = Stripe::StripeClient.new(connect_base: "https://other.stripe.com")
110
+ resp = OAuth.token(
111
+ { grant_type: "authorization_code", code: "this_is_an_authorization_code" },
112
+ client: client
113
+ )
114
+
115
+ assert_equal("sk_access_token", resp.access_token)
116
+ end
86
117
  end
87
118
 
88
119
  context ".deauthorize" do
@@ -99,6 +130,20 @@ module Stripe
99
130
  resp = OAuth.deauthorize(stripe_user_id: "acct_test_deauth")
100
131
  assert_equal("acct_test_deauth", resp.stripe_user_id)
101
132
  end
133
+
134
+ should "override the api base path when a StripeClient is provided" do
135
+ stub_request(:post, "https://other.stripe.com/oauth/deauthorize")
136
+ .with(body: {
137
+ "client_id" => "ca_test",
138
+ "stripe_user_id" => "acct_test_deauth",
139
+ })
140
+ .to_return(body: JSON.generate(stripe_user_id: "acct_test_deauth"))
141
+
142
+ client = Stripe::StripeClient.new(connect_base: "https://other.stripe.com")
143
+ resp = OAuth.deauthorize({ stripe_user_id: "acct_test_deauth" }, client: client)
144
+
145
+ assert_equal("acct_test_deauth", resp.stripe_user_id)
146
+ end
102
147
  end
103
148
  end
104
149
  end
@@ -4,6 +4,30 @@ require ::File.expand_path("../test_helper", __dir__)
4
4
 
5
5
  module Stripe
6
6
  class StripeClientTest < Test::Unit::TestCase
7
+ context "initializing a StripeClient" do
8
+ should "allow a String to be passed in order to set the api key" do
9
+ assert_equal StripeClient.new("test_123").config.api_key, "test_123"
10
+ end
11
+
12
+ should "allow for overrides via a Hash" do
13
+ config = { api_key: "test_123", open_timeout: 100 }
14
+ client = StripeClient.new(config)
15
+
16
+ assert_equal client.config.api_key, "test_123"
17
+ assert_equal client.config.open_timeout, 100
18
+ end
19
+
20
+ should "support deprecated ConnectionManager objects" do
21
+ assert StripeClient.new(Stripe::ConnectionManager.new).config.is_a?(Stripe::StripeConfiguration)
22
+ end
23
+
24
+ should "support passing a full configuration object" do
25
+ config = Stripe.config.reverse_duplicate_merge({ api_key: "test_123", open_timeout: 100 })
26
+ client = StripeClient.new(config)
27
+ assert_equal config, client.config
28
+ end
29
+ end
30
+
7
31
  context ".active_client" do
8
32
  should "be .default_client outside of #request" do
9
33
  assert_equal StripeClient.default_client, StripeClient.active_client
@@ -82,8 +106,64 @@ module Stripe
82
106
  assert_equal 1, StripeClient.maybe_gc_connection_managers
83
107
 
84
108
  # And as an additional check, the connection manager of the current
85
- # thread context should have been set to `nil` as it was GCed.
86
- assert_nil StripeClient.current_thread_context.default_connection_manager
109
+ # thread context should have been removed as it was GCed.
110
+ assert_equal({}, StripeClient.current_thread_context.default_connection_managers)
111
+ end
112
+
113
+ should "only garbage collect when all connection managers for a thread are expired" do
114
+ stub_request(:post, "#{Stripe.api_base}/v1/path")
115
+ .to_return(body: JSON.generate(object: "account"))
116
+
117
+ # Make sure we start with a blank slate (state may have been left in
118
+ # place by other tests).
119
+ StripeClient.clear_all_connection_managers
120
+
121
+ # Establish a base time.
122
+ t = 0.0
123
+
124
+ # And pretend that `StripeClient` was just initialized for the first
125
+ # time. (Don't access instance variables like this, but it's tricky to
126
+ # test properly otherwise.)
127
+ StripeClient.instance_variable_set(:@last_connection_manager_gc, t)
128
+
129
+ #
130
+ # t
131
+ #
132
+ Util.stubs(:monotonic_time).returns(t)
133
+
134
+ # Execute an initial request to ensure that a connection manager was
135
+ # created.
136
+ client = StripeClient.new
137
+ client.execute_request(:post, "/v1/path")
138
+
139
+ # Create a new client with a unique config to make sure the thread has two
140
+ # connection managers
141
+ active_client = StripeClient.new(max_network_retries: 10)
142
+ active_client.execute_request(:post, "/v1/path")
143
+
144
+ assert_equal 2, StripeClient.current_thread_context.default_connection_managers.keys.count
145
+ assert_equal nil, StripeClient.maybe_gc_connection_managers
146
+
147
+ # t + StripeClient::CONNECTION_MANAGER_GC_LAST_USED_EXPIRY + 1
148
+ #
149
+ # Move us far enough into the future that we're passed the horizons for
150
+ # both a GC run as well as well as the expiry age of a connection
151
+ # manager. That means the GC will run and collect the connection
152
+ # manager that we created above.
153
+ #
154
+ Util.stubs(:monotonic_time).returns(t + StripeClient::CONNECTION_MANAGER_GC_LAST_USED_EXPIRY + 1)
155
+
156
+ # Manually set the active_client's last_used time into the future to prevent GC.
157
+ StripeClient.default_connection_manager(active_client.config)
158
+ .instance_variable_set(:@last_used, Util.monotonic_time + 1)
159
+
160
+ assert_equal 0, StripeClient.maybe_gc_connection_managers
161
+
162
+ # Move time into the future past the last GC round
163
+ current_time = Util.monotonic_time
164
+ Util.stubs(:monotonic_time).returns(current_time * 2)
165
+
166
+ assert_equal 1, StripeClient.maybe_gc_connection_managers
87
167
  end
88
168
  end
89
169
 
@@ -129,6 +209,27 @@ module Stripe
129
209
  # And finally, give all threads time to perform their check.
130
210
  threads.each(&:join)
131
211
  end
212
+
213
+ should "clear only connection managers with a given configuration" do
214
+ StripeClient.clear_all_connection_managers
215
+
216
+ client1 = StripeClient.new(read_timeout: 5.0)
217
+ StripeClient.default_connection_manager(client1.config)
218
+ client2 = StripeClient.new(read_timeout: 2.0)
219
+ StripeClient.default_connection_manager(client2.config)
220
+
221
+ thread_contexts = StripeClient.instance_variable_get(:@thread_contexts_with_connection_managers)
222
+ assert_equal 1, thread_contexts.count
223
+ thread_context = thread_contexts.first
224
+
225
+ refute_nil thread_context.default_connection_managers[client1.config.key]
226
+ refute_nil thread_context.default_connection_managers[client2.config.key]
227
+
228
+ StripeClient.clear_all_connection_managers(config: client1.config)
229
+
230
+ assert_nil thread_context.default_connection_managers[client1.config.key]
231
+ refute_nil thread_context.default_connection_managers[client2.config.key]
232
+ end
132
233
  end
133
234
 
134
235
  context ".default_client" do
@@ -160,11 +261,28 @@ module Stripe
160
261
  thread.join
161
262
  refute_equal StripeClient.default_connection_manager, other_thread_manager
162
263
  end
264
+
265
+ should "create a separate connection manager per configuration" do
266
+ config = Stripe::StripeConfiguration.setup { |c| c.open_timeout = 100 }
267
+ connection_manager_one = StripeClient.default_connection_manager
268
+ connection_manager_two = StripeClient.default_connection_manager(config)
269
+
270
+ assert_equal connection_manager_one.config.open_timeout, 30
271
+ assert_equal connection_manager_two.config.open_timeout, 100
272
+ end
273
+
274
+ should "create a single connection manager for identical configurations" do
275
+ StripeClient.clear_all_connection_managers
276
+
277
+ 2.times { StripeClient.default_connection_manager(Stripe::StripeConfiguration.setup) }
278
+
279
+ assert_equal 1, StripeClient.instance_variable_get(:@thread_contexts_with_connection_managers).first.default_connection_managers.size
280
+ end
163
281
  end
164
282
 
165
283
  context ".should_retry?" do
166
284
  setup do
167
- Stripe.stubs(:max_network_retries).returns(2)
285
+ Stripe::StripeConfiguration.any_instance.stubs(:max_network_retries).returns(2)
168
286
  end
169
287
 
170
288
  should "retry on Errno::ECONNREFUSED" do
@@ -275,7 +393,7 @@ module Stripe
275
393
  context ".sleep_time" do
276
394
  should "should grow exponentially" do
277
395
  StripeClient.stubs(:rand).returns(1)
278
- Stripe.stubs(:max_network_retry_delay).returns(999)
396
+ Stripe.config.stubs(:max_network_retry_delay).returns(999)
279
397
  assert_equal(Stripe.initial_network_retry_delay, StripeClient.sleep_time(1))
280
398
  assert_equal(Stripe.initial_network_retry_delay * 2, StripeClient.sleep_time(2))
281
399
  assert_equal(Stripe.initial_network_retry_delay * 4, StripeClient.sleep_time(3))
@@ -284,8 +402,8 @@ module Stripe
284
402
 
285
403
  should "enforce the max_network_retry_delay" do
286
404
  StripeClient.stubs(:rand).returns(1)
287
- Stripe.stubs(:initial_network_retry_delay).returns(1)
288
- Stripe.stubs(:max_network_retry_delay).returns(2)
405
+ Stripe.config.stubs(:initial_network_retry_delay).returns(1)
406
+ Stripe.config.stubs(:max_network_retry_delay).returns(2)
289
407
  assert_equal(1, StripeClient.sleep_time(1))
290
408
  assert_equal(2, StripeClient.sleep_time(2))
291
409
  assert_equal(2, StripeClient.sleep_time(3))
@@ -295,8 +413,8 @@ module Stripe
295
413
  should "add some randomness" do
296
414
  random_value = 0.8
297
415
  StripeClient.stubs(:rand).returns(random_value)
298
- Stripe.stubs(:initial_network_retry_delay).returns(1)
299
- Stripe.stubs(:max_network_retry_delay).returns(8)
416
+ Stripe.config.stubs(:initial_network_retry_delay).returns(1)
417
+ Stripe.config.stubs(:max_network_retry_delay).returns(8)
300
418
 
301
419
  base_value = Stripe.initial_network_retry_delay * (0.5 * (1 + random_value))
302
420
 
@@ -309,6 +427,23 @@ module Stripe
309
427
  assert_equal(base_value * 4, StripeClient.sleep_time(3))
310
428
  assert_equal(base_value * 8, StripeClient.sleep_time(4))
311
429
  end
430
+
431
+ should "permit passing in a configuration object" do
432
+ StripeClient.stubs(:rand).returns(1)
433
+ config = Stripe::StripeConfiguration.setup do |c|
434
+ c.initial_network_retry_delay = 1
435
+ c.max_network_retry_delay = 2
436
+ end
437
+
438
+ # Set the global configuration to be different than the client
439
+ Stripe.config.stubs(:initial_network_retry_delay).returns(100)
440
+ Stripe.config.stubs(:max_network_retry_delay).returns(200)
441
+
442
+ assert_equal(1, StripeClient.sleep_time(1, config: config))
443
+ assert_equal(2, StripeClient.sleep_time(2, config: config))
444
+ assert_equal(2, StripeClient.sleep_time(3, config: config))
445
+ assert_equal(2, StripeClient.sleep_time(4, config: config))
446
+ end
312
447
  end
313
448
 
314
449
  context "#execute_request" do
@@ -342,6 +477,10 @@ module Stripe
342
477
  # switch over to rspec-mocks at some point, we can probably remove
343
478
  # this.
344
479
  Util.stubs(:monotonic_time).returns(0.0)
480
+
481
+ # Stub the Stripe.config so that mocha matchers will succeed. Currently,
482
+ # mocha does not support using param matchers within hashes.
483
+ StripeClient.any_instance.stubs(:config).returns(Stripe.config)
345
484
  end
346
485
 
347
486
  should "produce appropriate logging" do
@@ -353,11 +492,13 @@ module Stripe
353
492
  idempotency_key: "abc",
354
493
  method: :post,
355
494
  num_retries: 0,
356
- path: "/v1/account")
495
+ path: "/v1/account",
496
+ config: Stripe.config)
357
497
  Util.expects(:log_debug).with("Request details",
358
498
  body: "",
359
499
  idempotency_key: "abc",
360
- query: nil)
500
+ query: nil,
501
+ config: Stripe.config)
361
502
 
362
503
  Util.expects(:log_info).with("Response from Stripe API",
363
504
  account: "acct_123",
@@ -367,15 +508,18 @@ module Stripe
367
508
  method: :post,
368
509
  path: "/v1/account",
369
510
  request_id: "req_123",
370
- status: 200)
511
+ status: 200,
512
+ config: Stripe.config)
371
513
  Util.expects(:log_debug).with("Response details",
372
514
  body: body,
373
515
  idempotency_key: "abc",
374
- request_id: "req_123")
516
+ request_id: "req_123",
517
+ config: Stripe.config)
375
518
  Util.expects(:log_debug).with("Dashboard link for request",
376
519
  idempotency_key: "abc",
377
520
  request_id: "req_123",
378
- url: Util.request_id_dashboard_url("req_123", Stripe.api_key))
521
+ url: Util.request_id_dashboard_url("req_123", Stripe.api_key),
522
+ config: Stripe.config)
379
523
 
380
524
  stub_request(:post, "#{Stripe.api_base}/v1/account")
381
525
  .to_return(
@@ -404,7 +548,8 @@ module Stripe
404
548
  idempotency_key: nil,
405
549
  method: :post,
406
550
  num_retries: 0,
407
- path: "/v1/account")
551
+ path: "/v1/account",
552
+ config: Stripe.config)
408
553
  Util.expects(:log_info).with("Response from Stripe API",
409
554
  account: nil,
410
555
  api_version: nil,
@@ -413,7 +558,8 @@ module Stripe
413
558
  method: :post,
414
559
  path: "/v1/account",
415
560
  request_id: nil,
416
- status: 500)
561
+ status: 500,
562
+ config: Stripe.config)
417
563
 
418
564
  error = {
419
565
  code: "code",
@@ -428,7 +574,8 @@ module Stripe
428
574
  error_param: error[:param],
429
575
  error_type: error[:type],
430
576
  idempotency_key: nil,
431
- request_id: nil)
577
+ request_id: nil,
578
+ config: Stripe.config)
432
579
 
433
580
  stub_request(:post, "#{Stripe.api_base}/v1/account")
434
581
  .to_return(
@@ -449,7 +596,8 @@ module Stripe
449
596
  idempotency_key: nil,
450
597
  method: :post,
451
598
  num_retries: 0,
452
- path: "/oauth/token")
599
+ path: "/oauth/token",
600
+ config: Stripe.config)
453
601
  Util.expects(:log_info).with("Response from Stripe API",
454
602
  account: nil,
455
603
  api_version: nil,
@@ -458,14 +606,16 @@ module Stripe
458
606
  method: :post,
459
607
  path: "/oauth/token",
460
608
  request_id: nil,
461
- status: 400)
609
+ status: 400,
610
+ config: Stripe.config)
462
611
 
463
612
  Util.expects(:log_error).with("Stripe OAuth error",
464
613
  status: 400,
465
614
  error_code: "invalid_request",
466
615
  error_description: "No grant type specified",
467
616
  idempotency_key: nil,
468
- request_id: nil)
617
+ request_id: nil,
618
+ config: Stripe.config)
469
619
 
470
620
  stub_request(:post, "#{Stripe.connect_base}/oauth/token")
471
621
  .to_return(body: JSON.generate(error: "invalid_request",
@@ -788,7 +938,7 @@ module Stripe
788
938
 
789
939
  context "idempotency keys" do
790
940
  setup do
791
- Stripe.stubs(:max_network_retries).returns(2)
941
+ Stripe::StripeConfiguration.any_instance.stubs(:max_network_retries).returns(2)
792
942
  end
793
943
 
794
944
  should "not add an idempotency key to GET requests" do
@@ -838,7 +988,7 @@ module Stripe
838
988
 
839
989
  context "retry logic" do
840
990
  setup do
841
- Stripe.stubs(:max_network_retries).returns(2)
991
+ Stripe::StripeConfiguration.any_instance.stubs(:max_network_retries).returns(2)
842
992
  end
843
993
 
844
994
  should "retry failed requests and raise if error persists" do
@@ -870,6 +1020,21 @@ module Stripe
870
1020
  client = StripeClient.new
871
1021
  client.execute_request(:post, "/v1/charges")
872
1022
  end
1023
+
1024
+ should "pass the client configuration when retrying" do
1025
+ StripeClient.expects(:sleep_time)
1026
+ .with(any_of(1, 2),
1027
+ has_entry(:config, kind_of(Stripe::StripeConfiguration)))
1028
+ .at_least_once.returns(0)
1029
+
1030
+ stub_request(:post, "#{Stripe.api_base}/v1/charges")
1031
+ .to_raise(Errno::ECONNREFUSED.new)
1032
+
1033
+ client = StripeClient.new
1034
+ assert_raises Stripe::APIConnectionError do
1035
+ client.execute_request(:post, "/v1/charges")
1036
+ end
1037
+ end
873
1038
  end
874
1039
 
875
1040
  context "params serialization" do
@@ -1079,7 +1244,7 @@ module Stripe
1079
1244
  context "#proxy" do
1080
1245
  should "run the request through the proxy" do
1081
1246
  begin
1082
- StripeClient.current_thread_context.default_connection_manager = nil
1247
+ StripeClient.clear_all_connection_managers
1083
1248
 
1084
1249
  Stripe.proxy = "http://user:pass@localhost:8080"
1085
1250
 
@@ -1095,7 +1260,7 @@ module Stripe
1095
1260
  ensure
1096
1261
  Stripe.proxy = nil
1097
1262
 
1098
- StripeClient.current_thread_context.default_connection_manager = nil
1263
+ StripeClient.clear_all_connection_managers
1099
1264
  end
1100
1265
  end
1101
1266
  end