Skip to content

Commit 5f91b45

Browse files
authored
Merge pull request #25 from contentstack/feature/ruby-proxy
Feature/ruby proxy
2 parents 7c187e0 + 5596394 commit 5f91b45

File tree

3 files changed

+125
-13
lines changed

3 files changed

+125
-13
lines changed

lib/contentstack/api.rb

+93-10
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
module Contentstack
88
class API
99
using Utility
10-
def self.init_api(api_key, delivery_token, environment, host, branch, live_preview)
10+
def self.init_api(api_key, delivery_token, environment, host, branch, live_preview, proxy, retry_options)
1111
@host = host
1212
@api_version = '/v3'
1313
@environment = environment
@@ -16,6 +16,11 @@ def self.init_api(api_key, delivery_token, environment, host, branch, live_previ
1616
@branch = branch
1717
@headers = {environment: @environment}
1818
@live_preview = live_preview
19+
@proxy_details = proxy
20+
@timeout = retry_options["timeout"]
21+
@retryDelay = retry_options["retryDelay"]
22+
@retryLimit = retry_options["retryLimit"]
23+
@errorRetry = retry_options["errorRetry"]
1924
end
2025

2126
def self.live_preview_query(query= {})
@@ -29,7 +34,7 @@ def self.fetch_content_types(uid="")
2934
else
3035
path = "/content_types"
3136
end
32-
send_request(path, {})
37+
fetch_retry(path, {})
3338
end
3439

3540
def self.fetch_entries(content_type, query)
@@ -38,7 +43,7 @@ def self.fetch_entries(content_type, query)
3843
send_preview_request(path, query)
3944
else
4045
path = "/content_types/#{content_type}/entries"
41-
send_request(path, query)
46+
fetch_retry(path, query)
4247
end
4348
end
4449

@@ -48,22 +53,37 @@ def self.fetch_entry(content_type, entry_uid, query)
4853
send_preview_request(path, query)
4954
else
5055
path = "/content_types/#{content_type}/entries/#{entry_uid}"
51-
send_request(path, query)
56+
fetch_retry(path, query)
5257
end
5358
end
5459

5560
def self.get_assets(asset_uid=nil)
5661
path = "/assets"
5762
path += "/#{asset_uid}" if !asset_uid.nil?
58-
send_request(path)
63+
fetch_retry(path)
5964
end
6065

6166
def self.get_sync_items(query)
6267
path = "/stacks/sync"
63-
send_request(path, query)
68+
fetch_retry(path, query)
6469
end
6570

6671
private
72+
def self.fetch_retry(path, query=nil, count=0)
73+
response = send_request(path, query)
74+
if @errorRetry.include?(response["status_code"].to_i)
75+
if count < @retryLimit
76+
retryDelay_in_seconds = @retryDelay / 1000 #converting retry_delay from milliseconds into seconds
77+
sleep(retryDelay_in_seconds.to_i) #sleep method requires time in seconds as parameter
78+
response = fetch_retry(path, query, (count + 1))
79+
else
80+
raise Contentstack::Error.new(response) #Retry Limit exceeded
81+
end
82+
else
83+
response
84+
end
85+
end
86+
6787
def self.send_request(path, q=nil)
6888
q ||= {}
6989

@@ -75,12 +95,44 @@ def self.send_request(path, q=nil)
7595
"api_key" => @api_key,
7696
"access_token"=> @access_token,
7797
"user_agent"=> "ruby-sdk/#{Contentstack::VERSION}",
78-
"x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}"
98+
"x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}",
99+
"read_timeout" => @timeout
79100
}
80101
if !@branch.nil? && !@branch.empty?
81102
params["branch"] = @branch
82103
end
83-
ActiveSupport::JSON.decode(URI.open("#{@host}#{@api_version}#{path}#{query}", params).read)
104+
105+
begin
106+
if @proxy_details.empty?
107+
ActiveSupport::JSON.decode(URI.open("#{@host}#{@api_version}#{path}#{query}", params).read)
108+
elsif @proxy_details.present? && @proxy_details[:url].present? && @proxy_details[:port].present? && @proxy_details[:username].present? && @proxy_details[:password].present?
109+
proxy_uri = URI.parse("http://#{@proxy_details[:url]}:#{@proxy_details[:port]}/")
110+
proxy_username = @proxy_details[:username]
111+
proxy_password = @proxy_details[:password]
112+
113+
if !@branch.nil? && !@branch.empty?
114+
ActiveSupport::JSON.decode(URI.open("#{@host}#{@api_version}#{path}#{query}", :proxy_http_basic_authentication => [proxy_uri, proxy_username, proxy_password], "api_key" => @api_key, "access_token"=> @access_token, "user_agent"=> "ruby-sdk/#{Contentstack::VERSION}", "x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}", "read_timeout" => @timeout, "branch" => @branch).read)
115+
else
116+
ActiveSupport::JSON.decode(URI.open("#{@host}#{@api_version}#{path}#{query}", :proxy_http_basic_authentication => [proxy_uri, proxy_username, proxy_password], "api_key" => @api_key, "access_token"=> @access_token, "user_agent"=> "ruby-sdk/#{Contentstack::VERSION}", "x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}", "read_timeout" => @timeout).read)
117+
end
118+
elsif @proxy_details.present? && @proxy_details[:url].present? && @proxy_details[:port].present? && @proxy_details[:username].empty? && @proxy_details[:password].empty?
119+
proxy_uri = URI.parse("http://#{@proxy_details[:url]}:#{@proxy_details[:port]}/")
120+
121+
if !@branch.nil? && !@branch.empty?
122+
ActiveSupport::JSON.decode(URI.open("#{@host}#{@api_version}#{path}#{query}", "proxy" => proxy_uri, "api_key" => @api_key, "access_token"=> @access_token, "user_agent"=> "ruby-sdk/#{Contentstack::VERSION}", "x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}", "read_timeout" => @timeout, "branch" => @branch).read)
123+
else
124+
ActiveSupport::JSON.decode(URI.open("#{@host}#{@api_version}#{path}#{query}", "proxy" => proxy_uri, "api_key" => @api_key, "access_token"=> @access_token, "user_agent"=> "ruby-sdk/#{Contentstack::VERSION}", "x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}", "read_timeout" => @timeout).read)
125+
end
126+
end
127+
rescue OpenURI::HTTPError => error
128+
response = error.io
129+
#response.status
130+
# => ["503", "Service Unavailable"]
131+
error_response = JSON.parse(response.string)
132+
error_status = {"status_code" => response.status[0], "status_message" => response.status[1]}
133+
error = error_response.merge(error_status)
134+
raise Contentstack::Error.new(error.to_s)
135+
end
84136
end
85137

86138
def self.send_preview_request(path, q=nil)
@@ -94,12 +146,43 @@ def self.send_preview_request(path, q=nil)
94146
"api_key" => @api_key,
95147
"authorization" => @live_preview[:management_token],
96148
"user_agent"=> "ruby-sdk/#{Contentstack::VERSION}",
97-
"x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}"
149+
"x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}",
150+
"read_timeout" => @timeout
98151
}
99152
if !@branch.nil? && !@branch.empty?
100153
params["branch"] = @branch
101154
end
102-
ActiveSupport::JSON.decode(URI.open("#{preview_host}#{@api_version}#{path}#{query}",params).read)
155+
begin
156+
if @proxy_details.empty?
157+
ActiveSupport::JSON.decode(URI.open("#{preview_host}#{@api_version}#{path}#{query}",params).read)
158+
elsif @proxy_details.present? && @proxy_details[:url].present? && @proxy_details[:port].present? && @proxy_details[:username].present? && @proxy_details[:password].present?
159+
proxy_uri = URI.parse("http://#{@proxy_details[:url]}:#{@proxy_details[:port]}/")
160+
proxy_username = @proxy_details[:username]
161+
proxy_password = @proxy_details[:password]
162+
163+
if !@branch.nil? && !@branch.empty?
164+
ActiveSupport::JSON.decode(URI.open("#{preview_host}#{@api_version}#{path}#{query}", :proxy_http_basic_authentication => [proxy_uri, proxy_username, proxy_password], "api_key" => @api_key, "authorization" => @live_preview[:management_token], "user_agent"=> "ruby-sdk/#{Contentstack::VERSION}", "x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}", "read_timeout" => @timeout, "branch" => @branch).read)
165+
else
166+
ActiveSupport::JSON.decode(URI.open("#{preview_host}#{@api_version}#{path}#{query}", :proxy_http_basic_authentication => [proxy_uri, proxy_username, proxy_password], "api_key" => @api_key, "authorization" => @live_preview[:management_token], "user_agent"=> "ruby-sdk/#{Contentstack::VERSION}", "x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}", "read_timeout" => @timeout).read)
167+
end
168+
elsif @proxy_details.present? && @proxy_details[:url].present? && @proxy_details[:port].present? && @proxy_details[:username].empty? && @proxy_details[:password].empty?
169+
proxy_uri = URI.parse("http://#{@proxy_details[:url]}:#{@proxy_details[:port]}/")
170+
171+
if !@branch.nil? && !@branch.empty?
172+
ActiveSupport::JSON.decode(URI.open("#{preview_host}#{@api_version}#{path}#{query}", "proxy" => proxy_uri, "api_key" => @api_key, "authorization" => @live_preview[:management_token], "user_agent"=> "ruby-sdk/#{Contentstack::VERSION}", "x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}", "read_timeout" => @timeout, "branch" => @branch).read)
173+
else
174+
ActiveSupport::JSON.decode(URI.open("#{preview_host}#{@api_version}#{path}#{query}", "proxy" => proxy_uri, "api_key" => @api_key, "authorization" => @live_preview[:management_token], "user_agent"=> "ruby-sdk/#{Contentstack::VERSION}", "x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}", "read_timeout" => @timeout).read)
175+
end
176+
end
177+
rescue OpenURI::HTTPError => error
178+
response = error.io
179+
#response.status
180+
# => ["503", "Service Unavailable"]
181+
error_response = JSON.parse(response.string)
182+
error_status = {"status_code" => response.status[0], "status_message" => response.status[1]}
183+
error = error_response.merge(error_status)
184+
raise Contentstack::Error.new(error.to_s)
185+
end
103186
end
104187
end
105188
end

lib/contentstack/client.rb

+21-1
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,37 @@
33
require 'contentstack/asset_collection'
44
require 'contentstack/sync_result'
55
require 'util'
6+
require 'contentstack/error'
67
module Contentstack
78
class Client
89
using Utility
910
attr_reader :region, :host
1011
# Initialize "Contentstack" Client instance
1112
def initialize(api_key, delivery_token, environment, options={})
13+
raise Contentstack::Error.new("Api Key is not valid") if api_key.class != String
14+
raise Contentstack::Error.new("Api Key Field Should not be Empty") if api_key.empty?
15+
raise Contentstack::Error.new("Delivery Token is not valid") if delivery_token.class != String
16+
raise Contentstack::Error.new("Delivery Token Field Should not be Empty") if delivery_token.empty?
17+
raise Contentstack::Error.new("Envirnoment Field is not valid") if environment.class != String
18+
raise Contentstack::Error.new("Envirnoment Field Should not be Empty") if environment.empty?
1219
@region = options[:region].nil? ? Contentstack::Region::US : options[:region]
1320
@host = options[:host].nil? ? get_default_region_hosts(@region) : options[:host]
1421
@live_preview = !options.key?(:live_preview) ? {} : options[:live_preview]
1522
@branch = options[:branch].nil? ? "" : options[:branch]
16-
API.init_api(api_key, delivery_token, environment, @host, @branch, @live_preview)
23+
@proxy_details = options[:proxy].nil? ? "" : options[:proxy]
24+
@timeout = options[:timeout].nil? ? 3000 : options[:timeout]
25+
@retryDelay = options[:retryDelay].nil? ? 3000 : options[:retryDelay]
26+
@retryLimit = options[:retryLimit].nil? ? 5 : options[:retryLimit]
27+
@errorRetry = options[:errorRetry].nil? ? [408, 429] : options[:errorRetry]
28+
retry_options = {
29+
"timeout" => @timeout.to_s,
30+
"retryDelay"=> @retryDelay,
31+
"retryLimit"=> @retryLimit,
32+
"errorRetry" => @errorRetry
33+
}
34+
raise Contentstack::Error.new("Proxy URL Should not be Empty") if @proxy_details.present? && @proxy_details[:url].empty?
35+
raise Contentstack::Error.new("Proxy Port Should not be Empty") if @proxy_details.present? && @proxy_details[:port].empty?
36+
API.init_api(api_key, delivery_token, environment, @host, @branch, @live_preview, @proxy_details, retry_options)
1737
end
1838

1939
def content_types

lib/contentstack/query.rb

+11-2
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,14 @@ def not_equal_to(field_uid, value)
249249
# @param [String] field_uid UID of the field for which query should be executed
250250
# @param [String] values The possible values for the key's object
251251
#
252-
# Example
252+
# Example 1 - Array Equals Operator Within Group
253253
# @query = @stack.content_type('category').query
254254
# @query.contained_in("title", ["Electronics", "Apparel"])
255255
#
256+
# Example 2 - Array Equals Operator Within Modular Blocks
257+
# @query = @stack.content_type('category').query
258+
# @query.contained_in("additional_info.deals.deal_name", ["Christmas Deal", "Summer Deal"])
259+
#
256260
# @return [Contentstack::Query]
257261
def contained_in(field_uid, values)
258262
add_query_hash({:"#{field_uid}" => {"$in" => values}})
@@ -264,10 +268,14 @@ def contained_in(field_uid, values)
264268
# @param [String] field_uid UID of the field for which query should be executed
265269
# @param [String] values The possible values for the key's object
266270
#
267-
# Example
271+
# Example 1 - Array Not-equals Operator Within Group
268272
# @query = @stack.content_type('category').query
269273
# @query.not_contained_in("title", ["Electronics", "Apparel"])
270274
#
275+
# Example 2 - Array Not-equals Operator Within Modular Blocks
276+
# @query = @stack.content_type('category').query
277+
# @query.not_contained_in("additional_info.deals.deal_name", ["Christmas Deal", "Summer Deal"])
278+
#
271279
# @return [Contentstack::Query]
272280
def not_contained_in(field_uid, values)
273281
add_query_hash({:"#{field_uid}" => {"$nin" => values}})
@@ -377,6 +385,7 @@ def descending(field_uid)
377385
# @param [String] code The locale code of the entry
378386
#
379387
# Example
388+
# Change language method
380389
# @query = @stack.content_type('category').query
381390
# @query.locale('en-us')
382391
#

0 commit comments

Comments
 (0)