Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removing rest-client as a dependency & using native NET:HTTP #85

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ PATH
chargebee (2.46.0)
cgi (>= 0.1.0, < 1.0.0)
json_pure (~> 2.1)
rest-client (>= 1.8, <= 2.0.2)

GEM
remote: https://rubygems.org/
Expand All @@ -21,10 +20,6 @@ GEM
mime-types-data (3.2022.0105)
mocha (1.13.0)
netrc (0.11.0)
rest-client (2.0.2)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
rspec (3.0.0)
rspec-core (~> 3.0.0)
rspec-expectations (~> 3.0.0)
Expand All @@ -43,6 +38,7 @@ GEM

PLATFORMS
arm64-darwin-21
arm64-darwin-23
x86_64-darwin-20
x86_64-linux

Expand Down
13 changes: 13 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,16 @@ task :validate do
exit!
end
end

desc "Create tag v#{version} and build and push #{gem_file} to Rubygems for Beta version."
task :release_beta => :build do
unless `git branch` =~ /^\* next$/
puts "You must be on the next branch to release beta!"
exit!
end
sh "git commit --allow-empty -a -m 'Release #{version}'"
sh "git tag v#{version}"
sh "git push origin next"
sh "git push origin v#{version}"
sh "gem push pkg/#{name}-#{version}.gem"
end
5 changes: 2 additions & 3 deletions chargebee.gemspec

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still need to remove the line 26, right?

  s.add_dependency('rest-client', '>=1.8', '<=2.0.2')

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @formigarafa, thanks for the initial review! I’ve implemented the changes you suggested. Could you please re-review? Also, if possible, could you try running this in your test/sandbox environment to verify everything works as expected? Let us know if you encounter any issues.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Gem::Specification.new do |s|
s.rubygems_version = '1.3.5'
s.required_ruby_version = '>= 1.9.3'
s.name = 'chargebee'
s.version = '2.46.0'
s.version = '2.47.0.beta.1'
s.date = '2024-11-14'
s.summary = "Ruby client for Chargebee API."
s.description = "Subscription Billing - Simple. Secure. Affordable. More details at www.chargebee.com."
Expand All @@ -23,7 +23,6 @@ Gem::Specification.new do |s|
s.extra_rdoc_files = %w[README.md LICENSE]

s.add_dependency('json_pure', '~> 2.1')
s.add_dependency('rest-client', '>=1.8', '<=2.0.2')
s.add_dependency('cgi', '>=0.1.0', '<1.0.0')
s.add_development_dependency('rspec', '~> 3.0.0')
s.add_development_dependency('mocha')
Expand Down Expand Up @@ -123,8 +122,8 @@ Gem::Specification.new do |s|
lib/chargebee/models/unbilled_charge.rb
lib/chargebee/models/usage.rb
lib/chargebee/models/virtual_bank_account.rb
lib/chargebee/nativeRequest.rb
lib/chargebee/request.rb
lib/chargebee/rest.rb
lib/chargebee/result.rb
lib/chargebee/util.rb
lib/ssl/ca-certs.crt
Expand Down
4 changes: 2 additions & 2 deletions lib/chargebee.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require File.dirname(__FILE__) + '/chargebee/environment'
require File.dirname(__FILE__) + '/chargebee/rest'
require File.dirname(__FILE__) + '/chargebee/nativeRequest'
require File.dirname(__FILE__) + '/chargebee/util'
require File.dirname(__FILE__) + '/chargebee/request'
require File.dirname(__FILE__) + '/chargebee/result'
Expand Down Expand Up @@ -86,7 +86,7 @@

module ChargeBee

VERSION = '2.46.0'
VERSION = '2.47.0.beta.1'

@@default_env = nil
@@verify_ca_certs = true
Expand Down
136 changes: 136 additions & 0 deletions lib/chargebee/nativeRequest.rb
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
2 changes: 1 addition & 1 deletion lib/chargebee/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def self.send_list_request(method, url, params={}, env=nil, headers={})
def self.send(method, url, params={}, env=nil, headers={})
env ||= ChargeBee.default_env
ser_params = Util.serialize(params)
resp, rheaders = Rest.request(method, url, env, ser_params||={}, headers)
resp, rheaders = NativeRequest.request(method, url, env, ser_params||={}, headers)
if resp.has_key?(:list)
ListResult.new(resp[:list], resp[:next_offset], rheaders)
else
Expand Down
99 changes: 0 additions & 99 deletions lib/chargebee/rest.rb

This file was deleted.

2 changes: 1 addition & 1 deletion spec/chargebee/list_result_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
end

before do
ChargeBee::Rest.stubs(:request).returns(response)
ChargeBee::NativeRequest.stubs(:request).returns(response)
end

it "returns list object, with next offset attribute" do
Expand Down
11 changes: 5 additions & 6 deletions spec/chargebee_spec.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
require 'spec_helper'
require 'rest_client'
require 'sample_response'

describe "chargebee" do

before(:all) do
@request = RestClient::Request
@request = ChargeBee::NativeRequest
end

it "serialize should convert the hash to acceptable format" do
Expand Down Expand Up @@ -55,7 +54,7 @@
end

it "should properly convert the response json into proper object" do
@request.expects(:execute).once.returns(mock_response(simple_subscription, headers))
@request.expects(:request).once.returns([simple_subscription, headers])
result = ChargeBee::Subscription.retrieve("simple_subscription")
h = result.get_response_headers
expect(h).to eq(headers)
Expand All @@ -68,7 +67,7 @@
end

it "should properly convert the nested response json into proper object with sub types" do
@request.expects(:execute).once.returns(mock_response(nested_subscription, headers))
@request.expects(:request).once.returns([nested_subscription, headers])
result = ChargeBee::Subscription.retrieve("nested_subscription")
s = result.subscription
expect(s.id).to eq("nested_subscription")
Expand All @@ -80,7 +79,7 @@
end

it "should properly convert the list response json into proper result object" do
@request.expects(:execute).once.returns(mock_response(list_subscriptions, headers))
@request.expects(:request).once.returns([list_subscriptions, headers])
result = ChargeBee::Subscription.list({:limit => 2})
expect(result.length).to eq(2)
result.each do |i|
Expand All @@ -89,7 +88,7 @@
end

it "should parse event api response and provide the content properly" do
@request.expects(:execute).once.returns(mock_response(sample_event, headers))
@request.expects(:request).once.returns([sample_event, headers])
result = ChargeBee::Event.retrieve("sample_event")
event = result.event
s = event.content.subscription
Expand Down
Loading