diff --git a/lib/stripe/api_requestor.rb b/lib/stripe/api_requestor.rb index cf375dc5f..d4fa7804f 100644 --- a/lib/stripe/api_requestor.rb +++ b/lib/stripe/api_requestor.rb @@ -110,7 +110,7 @@ def self.should_retry?(error, return false if num_retries >= config.max_network_retries case error - when Net::OpenTimeout, Net::ReadTimeout + when Net::OpenTimeout, Net::ReadTimeout, Net::HTTPFatalError # Retry on timeout-related problems (either on open or read). true when EOFError, Errno::ECONNREFUSED, Errno::ECONNRESET, # rubocop:todo Lint/DuplicateBranch @@ -350,6 +350,7 @@ def last_response_has_key?(object_id) Errno::ETIMEDOUT => ERROR_MESSAGE_TIMEOUT_CONNECT, SocketError => ERROR_MESSAGE_CONNECTION, + Net::HTTPFatalError => ERROR_MESSAGE_CONNECTION, Net::OpenTimeout => ERROR_MESSAGE_TIMEOUT_CONNECT, Net::ReadTimeout => ERROR_MESSAGE_TIMEOUT_READ, diff --git a/test/stripe/api_requestor_test.rb b/test/stripe/api_requestor_test.rb index c916c6839..f91ccd000 100644 --- a/test/stripe/api_requestor_test.rb +++ b/test/stripe/api_requestor_test.rb @@ -317,6 +317,14 @@ class RequestorTest < Test::Unit::TestCase num_retries: 0) end + should "retry on Net::HTTPFatalError" do + response = Net::HTTPResponse::CODE_TO_OBJ["503"].new("1.1", "503", "Service Unavailable") + error = Net::HTTPFatalError.new("503 \"Service Unavailable\"", response) + + assert APIRequestor.should_retry?(error, + num_retries: 0) + end + should "retry on SocketError" do assert APIRequestor.should_retry?(SocketError.new, num_retries: 0) @@ -1178,6 +1186,23 @@ class RequestorTest < Test::Unit::TestCase assert_match(/Request was retried 2 times/, err.message) end + should "retry Net::HTTPFatalError failures and raise APIConnectionError if error persists" do + APIRequestor.expects(:sleep_time).at_least_once.returns(0) + + response = Net::HTTPResponse::CODE_TO_OBJ["503"].new("1.1", "503", "Service Unavailable") + error = Net::HTTPFatalError.new("503 \"Service Unavailable\"", response) + + stub_request(:post, "#{Stripe::DEFAULT_API_BASE}/v1/charges") + .to_raise(error) + + client = APIRequestor.new("sk_test_123") + err = assert_raises Stripe::APIConnectionError do + client.send(request_method, :post, "/v1/charges", :api, + &@read_body_chunk_block) + end + assert_match(/Request was retried 2 times/, err.message) + end + should "retry failed requests and return successful response" do APIRequestor.expects(:sleep_time).at_least_once.returns(0)