whiplash-app 0.5.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/lib/errors/whiplash_api_error.rb +5 -0
- data/lib/whiplash/app/caching.rb +2 -2
- data/lib/whiplash/app/connections.rb +73 -10
- data/lib/whiplash/app/signing.rb +5 -1
- data/lib/whiplash/app/version.rb +1 -1
- data/lib/whiplash/app.rb +36 -17
- data/whiplash-app.gemspec +1 -1
- metadata +7 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 216d093d7f7c804c1f6b7563a429e7d0ed70cf31e90eb56266e03c086107863a
|
4
|
+
data.tar.gz: bd62a9c2da9f0a603c13c7c40e99a0bfd1e6b48b958cd20f9c74f02613d3dd70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3ee8b0c5c9817ddbc3231889abe2d4edd95873234674c8a2da66e418cc262810a5424813f8144439a43fdc40765bc6e0fab10dfcb540cf9d6e2a1896393ae58
|
7
|
+
data.tar.gz: a2281f059a7d4c227d7d6a89cedeb75e082dcdaa2fb2799e9a3f36f205881f07813530ac120718035d702476c176a11e1f58a0a084e736790ede55f7991ef00c
|
data/.travis.yml
CHANGED
@@ -65,6 +65,10 @@ class WhiplashApiError < StandardError
|
|
65
65
|
class InternalServerError < WhiplashApiError
|
66
66
|
end
|
67
67
|
|
68
|
+
# 502
|
69
|
+
class Timeout < WhiplashApiError
|
70
|
+
end
|
71
|
+
|
68
72
|
# 503
|
69
73
|
class ServiceUnavailable < WhiplashApiError
|
70
74
|
end
|
@@ -88,6 +92,7 @@ class WhiplashApiError < StandardError
|
|
88
92
|
429 => WhiplashApiError::OverRateLimit,
|
89
93
|
495 => WhiplashApiError::SSLError,
|
90
94
|
500 => WhiplashApiError::InternalServerError,
|
95
|
+
502 => WhiplashApiError::Timeout,
|
91
96
|
503 => WhiplashApiError::ServiceUnavailable
|
92
97
|
}
|
93
98
|
end
|
data/lib/whiplash/app/caching.rb
CHANGED
@@ -7,13 +7,13 @@ module Whiplash
|
|
7
7
|
def cache_store
|
8
8
|
if ENV["REDIS_HOST"]
|
9
9
|
store = Moneta.new(:Redis, host: ENV["REDIS_HOST"], port: ENV["REDIS_PORT"], password: ENV["REDIS_PASSWORD"], expires: 7200)
|
10
|
-
Moneta::Namespace.new store, namespace_value
|
10
|
+
Moneta::Namespace.new store, Whiplash::App::Caching.namespace_value
|
11
11
|
else
|
12
12
|
Moneta.new(:File, dir: "tmp", expires: 7200)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def namespace_value
|
16
|
+
def self.namespace_value
|
17
17
|
ENV["REDIS_NAMESPACE"] || ENV["WHIPLASH_CLIENT_ID"]
|
18
18
|
end
|
19
19
|
|
@@ -2,6 +2,8 @@ module Whiplash
|
|
2
2
|
class App
|
3
3
|
module Connections
|
4
4
|
|
5
|
+
PER_PAGE_REQUEST_LIMIT = 50
|
6
|
+
|
5
7
|
def base_app_request(options={})
|
6
8
|
if options[:params][:id]
|
7
9
|
endpoint = [options[:endpoint], options[:params].delete(:id)].join('/')
|
@@ -11,6 +13,7 @@ module Whiplash
|
|
11
13
|
options[:headers] ||= {}
|
12
14
|
options[:headers][:customer_id] ||= customer_id if customer_id
|
13
15
|
options[:headers][:shop_id] ||= shop_id if shop_id
|
16
|
+
options[:headers][:version] ||= 2
|
14
17
|
|
15
18
|
args = [
|
16
19
|
options[:method],
|
@@ -32,7 +35,12 @@ module Whiplash
|
|
32
35
|
|
33
36
|
def app_request!(options = {})
|
34
37
|
begin
|
35
|
-
app_request(options)
|
38
|
+
response = app_request(options)
|
39
|
+
return response if response.success?
|
40
|
+
message = response.body if response.body.is_a? String
|
41
|
+
message = response.body.dig('error') if response.body.respond_to?(:dig)
|
42
|
+
store_whiplash_error!(response.status)
|
43
|
+
error_response(response.status, message)
|
36
44
|
rescue Faraday::ConnectionFailed => e
|
37
45
|
case e.message
|
38
46
|
when 'end of file reached'
|
@@ -49,11 +57,32 @@ module Whiplash
|
|
49
57
|
raise ProviderError::InternalServerError, e.message
|
50
58
|
end
|
51
59
|
end
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
60
|
+
end
|
61
|
+
|
62
|
+
def multi_page_get!(endpoint, params = {}, headers = nil)
|
63
|
+
results = []
|
64
|
+
page = 1
|
65
|
+
params[:per_page] = PER_PAGE_REQUEST_LIMIT
|
66
|
+
|
67
|
+
loop do
|
68
|
+
partial_results_request = app_request!(
|
69
|
+
method: :get,
|
70
|
+
endpoint: endpoint,
|
71
|
+
params: params,
|
72
|
+
headers: headers
|
73
|
+
).body
|
74
|
+
|
75
|
+
results << partial_results_request
|
76
|
+
results.flatten!
|
77
|
+
|
78
|
+
page += 1
|
79
|
+
params[:page] = page
|
80
|
+
|
81
|
+
break if partial_results_request.size == 0
|
82
|
+
break if partial_results_request.size < PER_PAGE_REQUEST_LIMIT
|
83
|
+
end
|
84
|
+
|
85
|
+
results
|
57
86
|
end
|
58
87
|
|
59
88
|
def delete(endpoint, params = {}, headers = nil)
|
@@ -112,10 +141,44 @@ module Whiplash
|
|
112
141
|
headers: headers)
|
113
142
|
end
|
114
143
|
|
144
|
+
def get_body_or_empty(endpoint, params = {}, headers = nil)
|
145
|
+
response = get(endpoint, params, headers)
|
146
|
+
if !response.success?
|
147
|
+
case response.status
|
148
|
+
when 500
|
149
|
+
Appsignal.send_error(WhiplashApiError::InternalServerError.new(response.body), {raised: false})
|
150
|
+
else
|
151
|
+
end
|
152
|
+
|
153
|
+
case get_context(endpoint)
|
154
|
+
when 'collection'
|
155
|
+
Rails.logger.info "[WhiplashApi] Returned #{response.status}. Returning an empty array..."
|
156
|
+
return []
|
157
|
+
when 'member'
|
158
|
+
Rails.logger.info "[WhiplashApi] Returned #{response.status}. Returning nil..."
|
159
|
+
return nil
|
160
|
+
when 'aggregate'
|
161
|
+
Rails.logger.info "[WhiplashApi] Returned #{response.status}. Returning an empty hash..."
|
162
|
+
return {}
|
163
|
+
end
|
164
|
+
end
|
165
|
+
response.body
|
166
|
+
end
|
167
|
+
|
168
|
+
def get_context(endpoint)
|
169
|
+
parts = endpoint.split('/').compact
|
170
|
+
return 'member' unless (parts.last =~ /\d+/).nil?
|
171
|
+
return 'aggregate' if parts.include?('aggregate')
|
172
|
+
'collection'
|
173
|
+
end
|
174
|
+
|
115
175
|
def sanitize_headers(headers)
|
116
|
-
if headers
|
117
|
-
|
118
|
-
|
176
|
+
return if headers.nil? || headers.empty?
|
177
|
+
out = {}.tap do |hash|
|
178
|
+
headers.each do |k,v|
|
179
|
+
if k.to_s == 'version'
|
180
|
+
hash['Accept-Version'] = "v#{v}"
|
181
|
+
else
|
119
182
|
hash["X-#{k.to_s.upcase.gsub('_','-')}"] = v.to_s
|
120
183
|
end
|
121
184
|
end
|
@@ -124,7 +187,7 @@ module Whiplash
|
|
124
187
|
|
125
188
|
def store_whiplash_error!(error, options={})
|
126
189
|
return unless defined?(Appsignal)
|
127
|
-
options
|
190
|
+
options.transform_keys!(&:to_sym)
|
128
191
|
Appsignal.increment_counter(
|
129
192
|
"whiplash_error",
|
130
193
|
1.0,
|
data/lib/whiplash/app/signing.rb
CHANGED
@@ -15,7 +15,11 @@ module Whiplash
|
|
15
15
|
private
|
16
16
|
|
17
17
|
def request_body(body)
|
18
|
-
|
18
|
+
begin
|
19
|
+
(body.nil? || body.empty?) ? ENV["WHIPLASH_CLIENT_ID"] : body
|
20
|
+
rescue NoMethodError => e
|
21
|
+
ENV["WHIPLASH_CLIENT_ID"]
|
22
|
+
end
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
data/lib/whiplash/app/version.rb
CHANGED
data/lib/whiplash/app.rb
CHANGED
@@ -4,6 +4,7 @@ require "whiplash/app/connections"
|
|
4
4
|
require "whiplash/app/finder_methods"
|
5
5
|
require "whiplash/app/signing"
|
6
6
|
require "whiplash/app/version"
|
7
|
+
require "errors/whiplash_api_error"
|
7
8
|
require "oauth2"
|
8
9
|
require "faraday_middleware"
|
9
10
|
|
@@ -18,18 +19,29 @@ module Whiplash
|
|
18
19
|
attr_accessor :customer_id, :shop_id, :token
|
19
20
|
|
20
21
|
def initialize(token=nil, options={})
|
21
|
-
|
22
|
+
token ||= cache_store["whiplash_api_token"]
|
22
23
|
@token = format_token(token) unless token.nil?
|
23
24
|
@customer_id = options[:customer_id]
|
24
25
|
@shop_id = options[:shop_id]
|
26
|
+
@api_version = options[:api_version] || 2 # can be 2_1
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.whiplash_api_token
|
30
|
+
store = Moneta.new(:Redis, host: ENV["REDIS_HOST"], port: ENV["REDIS_PORT"], password: ENV["REDIS_PASSWORD"], expires: 7200)
|
31
|
+
cache_store = Moneta::Namespace.new store, Whiplash::App::Caching.namespace_value
|
32
|
+
cache_store["whiplash_api_token"]
|
25
33
|
end
|
26
34
|
|
27
35
|
def client
|
28
36
|
OAuth2::Client.new(ENV["WHIPLASH_CLIENT_ID"], ENV["WHIPLASH_CLIENT_SECRET"], site: api_url)
|
29
37
|
end
|
30
38
|
|
39
|
+
def versioned_api_url
|
40
|
+
"api/v#{@api_version}"
|
41
|
+
end
|
42
|
+
|
31
43
|
def connection
|
32
|
-
out = Faraday.new [api_url,
|
44
|
+
out = Faraday.new [api_url, versioned_api_url].join("/") do |conn|
|
33
45
|
conn.request :oauth2, token.token, token_type: "bearer"
|
34
46
|
conn.request :json
|
35
47
|
conn.response :json, :content_type => /\bjson$/
|
@@ -44,34 +56,41 @@ module Whiplash
|
|
44
56
|
end
|
45
57
|
|
46
58
|
def refresh_token!
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
59
|
+
case ENV["WHIPLASH_CLIENT_SCOPE"]
|
60
|
+
when /app_(manage|read)/
|
61
|
+
begin
|
62
|
+
access_token = client.client_credentials.get_token(scope: ENV["WHIPLASH_CLIENT_SCOPE"])
|
63
|
+
new_token = access_token.to_hash
|
64
|
+
cache_store["whiplash_api_token"] = new_token
|
65
|
+
rescue URI::InvalidURIError => e
|
66
|
+
raise StandardError, "The provide URL (#{ENV["WHIPLASH_API_URL"]}) is not valid"
|
67
|
+
end
|
51
68
|
else
|
69
|
+
raise StandardError, "You must request an access token before you can refresh it" if token.nil?
|
70
|
+
raise StandardError, "Token must either be a Hash or an OAuth2::AccessToken" unless token.is_a?(OAuth2::AccessToken)
|
52
71
|
access_token = token.refresh!
|
53
72
|
end
|
54
73
|
self.token = access_token
|
55
74
|
end
|
56
75
|
|
57
76
|
def token_expired?
|
58
|
-
return token.expired? unless token.
|
59
|
-
return true unless cache_store.
|
60
|
-
return true if cache_store["whiplash_api_token"].
|
77
|
+
return token.expired? unless token.nil?
|
78
|
+
return true unless cache_store.key?("whiplash_api_token")
|
79
|
+
return true if cache_store["whiplash_api_token"].nil?
|
80
|
+
return true if cache_store["whiplash_api_token"].empty?
|
61
81
|
false
|
62
82
|
end
|
63
83
|
|
64
84
|
private
|
65
85
|
def format_token(oauth_token)
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
73
|
-
oauth_token = OAuth2::AccessToken.from_hash(client, oauth_token)
|
86
|
+
return oauth_token if oauth_token.is_a?(OAuth2::AccessToken)
|
87
|
+
raise StandardError, "Token must either be a Hash or an OAuth2::AccessToken" unless oauth_token.is_a?(Hash)
|
88
|
+
oauth_token['expires'] = oauth_token['expires'].to_s # from_hash expects 'true'
|
89
|
+
if oauth_token.has_key?('token')
|
90
|
+
oauth_token['access_token'] = oauth_token['token']
|
91
|
+
oauth_token.delete('token')
|
74
92
|
end
|
93
|
+
oauth_token = OAuth2::AccessToken.from_hash(client, oauth_token)
|
75
94
|
end
|
76
95
|
|
77
96
|
end
|
data/whiplash-app.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_dependency "faraday_middleware", "~> 0.11.0"
|
23
23
|
spec.add_dependency "moneta", "~> 0.8.0"
|
24
24
|
|
25
|
-
spec.add_development_dependency "bundler", "
|
25
|
+
spec.add_development_dependency "bundler", ">= 2.2"
|
26
26
|
spec.add_development_dependency "rake", ">= 12.3.3"
|
27
27
|
spec.add_development_dependency "rspec", "~> 3.0"
|
28
28
|
spec.add_development_dependency "pry" , '~> 0.12.2'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: whiplash-app
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Don Sullivan, Mark Dickson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oauth2
|
@@ -56,16 +56,16 @@ dependencies:
|
|
56
56
|
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '2.2'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '2.2'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -153,8 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
153
|
- !ruby/object:Gem::Version
|
154
154
|
version: '0'
|
155
155
|
requirements: []
|
156
|
-
|
157
|
-
rubygems_version: 2.7.6.2
|
156
|
+
rubygems_version: 3.0.3.1
|
158
157
|
signing_key:
|
159
158
|
specification_version: 4
|
160
159
|
summary: this gem provides connectivity to the Whiplash API for authentication and
|