Store the HTTP status code, HTTP body, and parsed JSON body on exceptions

This commit is contained in:
Greg Brockman 2012-01-25 16:59:56 -08:00
parent e05c49350b
commit cfef69ac06
2 changed files with 92 additions and 17 deletions

View File

@ -442,14 +442,26 @@ module Stripe
include Stripe::APIOperations::Create
end
class StripeError < StandardError; end
class StripeError < StandardError
attr_reader :message
attr_reader :http_status
attr_reader :http_body
attr_reader :json_body
def initialize(message=nil, http_status=nil, http_body=nil, json_body=nil)
@message = message
@http_status = http_status
@http_body = http_body
@json_body = json_body
end
end
class APIError < StripeError; end
class APIConnectionError < StripeError; end
class CardError < StripeError
attr_reader :param, :code
def initialize(message, param, code)
super(message)
def initialize(message, param, code, http_status=nil, http_body=nil, json_body=nil)
super(message, http_status, http_body, json_body)
@param = param
@code = code
end
@ -457,8 +469,8 @@ module Stripe
class InvalidRequestError < StripeError
attr_accessor :param
def initialize(message, param)
super(message)
def initialize(message, param, http_status=nil, http_body=nil, json_body=nil)
super(message, http_status, http_body, json_body)
@param = param
end
end
@ -568,7 +580,7 @@ module Stripe
# some library out there that makes symbolize_names not work.
resp = JSON.parse(rbody)
rescue JSON::ParserError
raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})")
raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})", rcode, rbody)
end
resp = Util.symbolize_names(resp)
@ -585,27 +597,27 @@ module Stripe
begin
error_obj = JSON.parse(rbody)
error_obj = Util.symbolize_names(error_obj)
error = error_obj[:error] or raise StripeError.new
error = error_obj[:error] or raise StripeError.new # escape from parsing
rescue JSON::ParserError, StripeError
raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})")
raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})", rcode, rbody)
end
case rcode
when 400, 404 then
raise invalid_request_error(error)
raise invalid_request_error(error, rcode, rbody, error_obj)
when 401
raise authentication_error(error)
raise authentication_error(error, rcode, rbody, error_obj)
when 402
raise card_error(error)
raise card_error(error, rcode, rbody, error_obj)
else
raise api_error(error)
raise api_error(error, rcode, rbody, error_obj)
end
end
def self.invalid_request_error(error); InvalidRequestError.new(error[:message], error[:param]); end
def self.authentication_error(error); AuthenticationError.new(error[:message]); end
def self.card_error(error); CardError.new(error[:message], error[:param], error[:code]); end
def self.api_error(error); APIError.new(error[:message]); end
def self.invalid_request_error(error, rcode, rbody, error_obj); InvalidRequestError.new(error[:message], error[:param], rcode, rbody, error_obj); end
def self.authentication_error(error, rcode, rbody, error_obj); AuthenticationError.new(error[:message], rcode, rbody, error_obj); end
def self.card_error(error, rcode, rbody, error_obj); CardError.new(error[:message], error[:param], error[:code], rcode, rbody, error_obj); end
def self.api_error(error, rcode, rbody, error_obj); APIError.new(error[:message], rcode, rbody, error_obj); end
def self.handle_restclient_error(e)
case e

View File

@ -73,13 +73,14 @@ class TestStripeRuby < Test::Unit::TestCase
end
should "not specifying api credentials should raise an exception" do
Stripe.api_key = nil
assert_raises Stripe::AuthenticationError do
Stripe::Customer.new("test_customer").refresh
end
end
should "specifying invalid api credentials should raise an exception" do
Stripe.api_key="invalid"
Stripe.api_key = "invalid"
response = test_response(test_invalid_api_key_error, 401)
assert_raises Stripe::AuthenticationError do
@mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 401))
@ -87,6 +88,20 @@ class TestStripeRuby < Test::Unit::TestCase
end
end
should "AuthenticationErrors should have an http status, http body, and JSON body" do
Stripe.api_key = "invalid"
response = test_response(test_invalid_api_key_error, 401)
begin
@mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 401))
Stripe::Customer.retrieve("failing_customer")
rescue Stripe::AuthenticationError => e
assert_equal(401, e.http_status)
assert_equal(true, !!e.http_body)
assert_equal(true, !!e.json_body[:error][:message])
assert_equal(test_invalid_api_key_error['error']['message'], e.json_body[:error][:message])
end
end
context "with valid credentials" do
setup do
Stripe.api_key="foo"
@ -96,6 +111,54 @@ class TestStripeRuby < Test::Unit::TestCase
Stripe.api_key=nil
end
should "a 400 should give an InvalidRequestError with http status, body, and JSON body" do
response = test_response(test_missing_id_error, 400)
@mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
begin
Stripe::Customer.retrieve("foo")
rescue Stripe::InvalidRequestError => e
assert_equal(400, e.http_status)
assert_equal(true, !!e.http_body)
assert_equal(true, e.json_body.kind_of?(Hash))
end
end
should "a 401 should give an AuthenticationError with http status, body, and JSON body" do
response = test_response(test_missing_id_error, 401)
@mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
begin
Stripe::Customer.retrieve("foo")
rescue Stripe::AuthenticationError => e
assert_equal(401, e.http_status)
assert_equal(true, !!e.http_body)
assert_equal(true, e.json_body.kind_of?(Hash))
end
end
should "a 402 should give a CardError with http status, body, and JSON body" do
response = test_response(test_missing_id_error, 402)
@mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
begin
Stripe::Customer.retrieve("foo")
rescue Stripe::CardError => e
assert_equal(402, e.http_status)
assert_equal(true, !!e.http_body)
assert_equal(true, e.json_body.kind_of?(Hash))
end
end
should "a 404 should give an InvalidRequestError with http status, body, and JSON body" do
response = test_response(test_missing_id_error, 404)
@mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 404))
begin
Stripe::Customer.retrieve("foo")
rescue Stripe::InvalidRequestError => e
assert_equal(404, e.http_status)
assert_equal(true, !!e.http_body)
assert_equal(true, e.json_body.kind_of?(Hash))
end
end
should "setting a nil value for a param should exclude that param from the request" do
@mock.expects(:get).with('https://api.stripe.com/v1/charges', { :offset => 5, :sad => false }, nil).returns(test_response({ :count => 1, :data => [test_charge] }))
c = Stripe::Charge.all(:count => nil, :offset => 5, :sad => false)