-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Releasing v2.49.0. Please check the changelog for the updates.
- Loading branch information
Showing
9 changed files
with
173 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
require 'json' | ||
require 'net/http' | ||
require 'uri' | ||
require 'stringio' | ||
|
||
module ChargeBee | ||
module NativeRequest | ||
|
||
def self.request(method, url, env, params = nil, headers = {}) | ||
raise Error.new('No environment configured.') unless env | ||
api_key = env.api_key | ||
|
||
uri = URI(env.api_url(url)) | ||
|
||
case method.to_s.downcase.to_sym | ||
when :get, :head, :delete | ||
uri.query = URI.encode_www_form(params) if params | ||
payload = nil | ||
else | ||
payload = URI.encode_www_form(params || {}) | ||
end | ||
user_agent = ChargeBee.user_agent | ||
headers = { | ||
"User-Agent" => user_agent, | ||
"Accept" => "application/json", | ||
"Lang-Version" => RUBY_VERSION, | ||
"OS-Version" => RUBY_PLATFORM, | ||
"Content-Type" => "application/x-www-form-urlencoded" | ||
}.merge(headers) | ||
|
||
http = Net::HTTP.new(uri.host, uri.port) | ||
http.use_ssl = true | ||
http.open_timeout=env.connect_timeout | ||
http.read_timeout=env.read_timeout | ||
if ChargeBee.verify_ca_certs? | ||
http.verify_mode = OpenSSL::SSL::VERIFY_PEER | ||
http.ca_file = ChargeBee.ca_cert_path | ||
else | ||
http.verify_mode = OpenSSL::SSL::VERIFY_NONE | ||
end | ||
|
||
request_class = case method.to_s.downcase.to_sym | ||
when :get then Net::HTTP::Get | ||
when :post then Net::HTTP::Post | ||
when :put then Net::HTTP::Put | ||
when :delete then Net::HTTP::Delete | ||
else raise Error.new("Unsupported HTTP method: #{method}") | ||
end | ||
|
||
request = request_class.new(uri, headers) | ||
request.body = payload if payload | ||
|
||
request.basic_auth(api_key, nil) | ||
begin | ||
response = http.request(request) | ||
rescue => e | ||
raise IOError.new("IO Exception when trying to connect to ChargeBee with URL #{uri} . Reason: #{e}", e) | ||
end | ||
handle_response(response, headers) | ||
end | ||
|
||
def self.handle_response(response, headers) | ||
rcode = response.code.to_i | ||
rbody = response.body | ||
|
||
# converting headers to rest-client format previously we were using rest-client, | ||
# and mapping headers to that format to support backward compatability | ||
rheaders = beautify_headers(response.to_hash) | ||
|
||
# When a custom 'Accept-Encoding' header is set to gzip, Net::HTTP will not automatically | ||
# decompress the response. Therefore, we need to manually handle decompression | ||
# based on the 'Content-Encoding' header in the response. | ||
# https://github.com/ruby/ruby/blob/19c1f0233eb5202403c52b196f1d573893eacab7/lib/net/http/generic_request.rb#L82 | ||
if headers.keys.any? { |k| k.downcase == 'accept-encoding' } && rheaders[:content_encoding] == 'gzip' && rbody && !rbody.empty? | ||
rbody = Zlib::GzipReader.new(StringIO.new(rbody)).read | ||
end | ||
|
||
if rcode >= 200 && rcode < 300 | ||
begin | ||
resp = JSON.parse(rbody) | ||
rescue JSON::ParserError => e | ||
raise handle_json_error(rbody, e) | ||
end | ||
return Util.symbolize_keys(resp), rheaders | ||
else | ||
raise handle_for_error(rcode, rbody) | ||
end | ||
end | ||
|
||
def self.handle_json_error(rbody, e) | ||
if rbody.include?("503") | ||
raise Error.new("Sorry, the server is currently unable to handle the request due to a temporary overload or scheduled maintenance. Please retry after sometime. \n type: internal_temporary_error, \n http_status_code: 503, \n error_code: internal_temporary_error,\n content: #{rbody.inspect}",e) | ||
elsif rbody.include?("504") | ||
raise Error.new("The server did not receive a timely response from an upstream server, request aborted. If this problem persists, contact us at [email protected]. \n type: gateway_timeout, \n http_status_code: 504, \n error_code: gateway_timeout,\n content: #{rbody.inspect}",e) | ||
else | ||
raise Error.new("Sorry, something went wrong when trying to process the request. If this problem persists, contact us at [email protected]. \n type: internal_error, \n http_status_code: 500, \n error_code: internal_error,\n content: #{rbody.inspect}",e) | ||
end | ||
end | ||
|
||
def self.handle_for_error(rcode, rbody) | ||
return Error.new("No response returned by ChargeBee API. HTTP status code: #{rcode}") if rcode == 204 | ||
begin | ||
error_obj = JSON.parse(rbody) | ||
error_obj = Util.symbolize_keys(error_obj) | ||
rescue Exception => e | ||
raise Error.new("Error response not in JSON format. The http status code is #{rcode} \n #{rbody.inspect}",e) | ||
end | ||
type = error_obj[:type] | ||
case type | ||
when "payment" | ||
raise PaymentError.new(rcode, error_obj) | ||
when "operation_failed" | ||
raise OperationFailedError.new(rcode, error_obj) | ||
when "invalid_request" | ||
raise InvalidRequestError.new(rcode, error_obj) | ||
else | ||
raise APIError.new(rcode, error_obj) | ||
end | ||
end | ||
# directly copying headers formatting from rest-client to support backward compatability for rest-client | ||
def self.beautify_headers(headers) | ||
headers.inject({}) do |out, (key, value)| | ||
key_sym = key.tr('-', '_').downcase.to_sym | ||
|
||
# Handle Set-Cookie specially since it cannot be joined by comma. | ||
if key.downcase == 'set-cookie' | ||
out[key_sym] = value | ||
else | ||
out[key_sym] = value.join(', ') | ||
end | ||
|
||
out | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters