stripe 1.45.0 → 1.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.txt +4 -0
- data/VERSION +1 -1
- data/lib/stripe.rb +61 -21
- data/lib/stripe/version.rb +1 -1
- data/test/stripe/api_resource_test.rb +32 -27
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d883d1c0eb0486e3c51e5076178c4351ca70ee68
|
4
|
+
data.tar.gz: a992c6c4e854019538a0406dbca5382c8f99d77e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: caf72f6851481ed302b8d06d450b55cf72c260104e549c099f52bb7477ec0ec28777648f4d3e4edae0f1c96cfec8123248a645cb316325cefec4f04cab74fab8
|
7
|
+
data.tar.gz: 165a6679fea615754af43de70e04c5d33a225ad1e938222e7c13767736bcdd9955162b22f266044f20818758ec3bcae0bb366c1c641b3fe1a388ed441315264b
|
data/History.txt
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.46.0
|
data/lib/stripe.rb
CHANGED
@@ -68,6 +68,23 @@ require 'stripe/errors/rate_limit_error'
|
|
68
68
|
module Stripe
|
69
69
|
DEFAULT_CA_BUNDLE_PATH = File.dirname(__FILE__) + '/data/ca-certificates.crt'
|
70
70
|
|
71
|
+
# HTTP status exceptions which we'd like to retry. Most HTTP status
|
72
|
+
# exceptions are from a Stripe API server response, so we generally _don't_
|
73
|
+
# retry because doing so would have the same result as the original request.
|
74
|
+
RETRY_HTTP_EXCEPTIONS = [
|
75
|
+
# A server may respond with a 409 to indicate that there is a concurrent
|
76
|
+
# request executing with the same idempotency key. In the case that a
|
77
|
+
# request failed due to a connection problem and the client has retried too
|
78
|
+
# early, but the server is still executing the old request, we would like
|
79
|
+
# the client to continue retrying until getting a "real" response status
|
80
|
+
# back.
|
81
|
+
RestClient::Conflict,
|
82
|
+
|
83
|
+
# Retry on timeout-related problems. This shouldn't be lumped in with HTTP
|
84
|
+
# exceptions, but with RestClient it is.
|
85
|
+
RestClient::RequestTimeout,
|
86
|
+
].freeze
|
87
|
+
|
71
88
|
@api_base = 'https://api.stripe.com'
|
72
89
|
@connect_base = 'https://connect.stripe.com'
|
73
90
|
@uploads_base = 'https://uploads.stripe.com'
|
@@ -194,24 +211,45 @@ module Stripe
|
|
194
211
|
def self.execute_request_with_rescues(request_opts, api_base_url, retry_count = 0)
|
195
212
|
begin
|
196
213
|
response = execute_request(request_opts)
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
214
|
+
|
215
|
+
# We rescue all exceptions from a request so that we have an easy spot to
|
216
|
+
# implement our retry logic across the board. We'll re-raise if it's a type
|
217
|
+
# of exception that we didn't expect to handle.
|
218
|
+
rescue => e
|
219
|
+
if should_retry?(e, retry_count)
|
220
|
+
retry_count = retry_count + 1
|
221
|
+
sleep sleep_time(retry_count)
|
222
|
+
retry
|
223
|
+
end
|
224
|
+
|
225
|
+
case e
|
226
|
+
when SocketError
|
227
|
+
response = handle_restclient_error(e, request_opts, retry_count, api_base_url)
|
228
|
+
|
229
|
+
when NoMethodError
|
230
|
+
# Work around RestClient bug
|
231
|
+
if e.message =~ /\WRequestFailed\W/
|
232
|
+
e = APIConnectionError.new('Unexpected HTTP response code')
|
233
|
+
response = handle_restclient_error(e, request_opts, retry_count, api_base_url)
|
234
|
+
else
|
235
|
+
raise
|
236
|
+
end
|
237
|
+
|
238
|
+
when RestClient::ExceptionWithResponse
|
239
|
+
if e.response
|
240
|
+
handle_api_error(e.response)
|
241
|
+
else
|
242
|
+
response = handle_restclient_error(e, request_opts, retry_count, api_base_url)
|
243
|
+
end
|
244
|
+
|
245
|
+
when RestClient::Exception, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError
|
203
246
|
response = handle_restclient_error(e, request_opts, retry_count, api_base_url)
|
247
|
+
|
248
|
+
# Only handle errors when we know we can do so, and re-raise otherwise.
|
249
|
+
# This should be pretty infrequent.
|
204
250
|
else
|
205
251
|
raise
|
206
252
|
end
|
207
|
-
rescue RestClient::ExceptionWithResponse => e
|
208
|
-
if e.response
|
209
|
-
handle_api_error(e.response)
|
210
|
-
else
|
211
|
-
response = handle_restclient_error(e, request_opts, retry_count, api_base_url)
|
212
|
-
end
|
213
|
-
rescue RestClient::Exception, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => e
|
214
|
-
response = handle_restclient_error(e, request_opts, retry_count, api_base_url)
|
215
253
|
end
|
216
254
|
|
217
255
|
response
|
@@ -367,13 +405,6 @@ module Stripe
|
|
367
405
|
|
368
406
|
def self.handle_restclient_error(e, request_opts, retry_count, api_base_url=nil)
|
369
407
|
|
370
|
-
if should_retry?(e, retry_count)
|
371
|
-
retry_count = retry_count + 1
|
372
|
-
sleep sleep_time(retry_count)
|
373
|
-
response = execute_request_with_rescues(request_opts, api_base_url, retry_count)
|
374
|
-
return response
|
375
|
-
end
|
376
|
-
|
377
408
|
api_base_url = @api_base unless api_base_url
|
378
409
|
connection_message = "Please check your internet connection and try again. " \
|
379
410
|
"If this problem persists, you should check Stripe's service status at " \
|
@@ -419,7 +450,16 @@ module Stripe
|
|
419
450
|
|
420
451
|
def self.should_retry?(e, retry_count)
|
421
452
|
return false if retry_count >= self.max_network_retries
|
453
|
+
|
454
|
+
# Certificate validation problem: do not retry.
|
422
455
|
return false if e.is_a?(RestClient::SSLCertificateNotVerified)
|
456
|
+
|
457
|
+
# Generally don't retry when we got a successful response back from the
|
458
|
+
# Stripe API server, but with some exceptions (for more details, see notes
|
459
|
+
# on RETRY_HTTP_EXCEPTIONS).
|
460
|
+
return false if e.is_a?(RestClient::ExceptionWithResponse) &&
|
461
|
+
!RETRY_HTTP_EXCEPTIONS.any? { |klass| e.is_a?(klass) }
|
462
|
+
|
423
463
|
return true
|
424
464
|
end
|
425
465
|
|
data/lib/stripe/version.rb
CHANGED
@@ -685,14 +685,14 @@ module Stripe
|
|
685
685
|
end
|
686
686
|
|
687
687
|
context "with retries" do
|
688
|
-
|
689
688
|
setup do
|
690
689
|
Stripe.stubs(:max_network_retries).returns(2)
|
691
690
|
end
|
692
691
|
|
693
692
|
should 'retry failed network requests if specified and raise if error persists' do
|
694
693
|
Stripe.expects(:sleep_time).at_least_once.returns(0)
|
695
|
-
@mock.expects(:post).times(3).with('https://api.stripe.com/v1/charges', nil, 'amount=50¤cy=usd').
|
694
|
+
@mock.expects(:post).times(3).with('https://api.stripe.com/v1/charges', nil, 'amount=50¤cy=usd').
|
695
|
+
raises(Errno::ECONNREFUSED.new)
|
696
696
|
|
697
697
|
err = assert_raises Stripe::APIConnectionError do
|
698
698
|
Stripe::Charge.create(:amount => 50, :currency => 'usd', :card => { :number => nil })
|
@@ -704,34 +704,15 @@ module Stripe
|
|
704
704
|
Stripe.expects(:sleep_time).at_least_once.returns(0)
|
705
705
|
response = make_response({"id" => "myid"})
|
706
706
|
err = Errno::ECONNREFUSED.new
|
707
|
-
@mock.expects(:post).times(2).with('https://api.stripe.com/v1/charges', nil, 'amount=50¤cy=usd').
|
707
|
+
@mock.expects(:post).times(2).with('https://api.stripe.com/v1/charges', nil, 'amount=50¤cy=usd').
|
708
|
+
raises(Errno::ECONNREFUSED.new).
|
709
|
+
then.
|
710
|
+
returns(response)
|
708
711
|
|
709
712
|
result = Stripe::Charge.create(:amount => 50, :currency => 'usd', :card => { :number => nil })
|
710
713
|
assert_equal "myid", result.id
|
711
714
|
end
|
712
715
|
|
713
|
-
# We retry the request if we receive SSL errors, since these can be caused
|
714
|
-
# by transient network issues, in addition to compatibility issues between
|
715
|
-
# the client and server.
|
716
|
-
should 'retry failed network requests if they fail with OpenSSL::SSL::SSLError' do
|
717
|
-
Stripe.expects(:sleep_time).at_least_once.returns(0)
|
718
|
-
@mock.expects(:post).times(3).with('https://api.stripe.com/v1/charges', nil, 'amount=50¤cy=usd').raises(OpenSSL::SSL::SSLError.new('message'))
|
719
|
-
|
720
|
-
err = assert_raises Stripe::APIConnectionError do
|
721
|
-
Stripe::Charge.create(:amount => 50, :currency => 'usd', :card => { :number => nil })
|
722
|
-
end
|
723
|
-
assert_match(/Request was retried 2 times/, err.message)
|
724
|
-
end
|
725
|
-
|
726
|
-
should 'not retry a SSLCertificateNotVerified error' do
|
727
|
-
@mock.expects(:post).times(1).with('https://api.stripe.com/v1/charges', nil, 'amount=50¤cy=usd').raises(RestClient::SSLCertificateNotVerified.new('message'))
|
728
|
-
|
729
|
-
err = assert_raises Stripe::APIConnectionError do
|
730
|
-
Stripe::Charge.create(:amount => 50, :currency => 'usd', :card => { :number => nil })
|
731
|
-
end
|
732
|
-
assert_no_match(/retried/, err.message)
|
733
|
-
end
|
734
|
-
|
735
716
|
should 'not add an idempotency key to GET requests' do
|
736
717
|
SecureRandom.expects(:uuid).times(0)
|
737
718
|
Stripe.expects(:execute_request).with do |opts|
|
@@ -770,8 +751,33 @@ module Stripe
|
|
770
751
|
|
771
752
|
end
|
772
753
|
|
773
|
-
context "
|
754
|
+
context ".should_retry?" do
|
755
|
+
setup do
|
756
|
+
Stripe.stubs(:max_network_retries).returns(2)
|
757
|
+
end
|
758
|
+
|
759
|
+
should 'retry on a low-level network error' do
|
760
|
+
assert Stripe.should_retry?(Errno::ECONNREFUSED.new, 0)
|
761
|
+
end
|
762
|
+
|
763
|
+
should 'retry on timeout' do
|
764
|
+
assert Stripe.should_retry?(RestClient::RequestTimeout.new, 0)
|
765
|
+
end
|
774
766
|
|
767
|
+
should 'retry on a conflict' do
|
768
|
+
assert Stripe.should_retry?(RestClient::Conflict.new, 0)
|
769
|
+
end
|
770
|
+
|
771
|
+
should 'not retry at maximum count' do
|
772
|
+
refute Stripe.should_retry?(RuntimeError.new, Stripe.max_network_retries)
|
773
|
+
end
|
774
|
+
|
775
|
+
should 'not retry on a certificate validation error' do
|
776
|
+
refute Stripe.should_retry?(RestClient::SSLCertificateNotVerified.new('message'), 0)
|
777
|
+
end
|
778
|
+
end
|
779
|
+
|
780
|
+
context ".sleep_time" do
|
775
781
|
should "should grow exponentially" do
|
776
782
|
Stripe.stubs(:rand).returns(1)
|
777
783
|
Stripe.stubs(:max_network_retry_delay).returns(999)
|
@@ -808,7 +814,6 @@ module Stripe
|
|
808
814
|
assert_equal(base_value * 4, Stripe.sleep_time(3))
|
809
815
|
assert_equal(base_value * 8, Stripe.sleep_time(4))
|
810
816
|
end
|
811
|
-
|
812
817
|
end
|
813
818
|
end
|
814
819
|
end
|