ncore 2.3.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 57e1ee1a969b6a8679b297f537fe6d2c6d95418d75db88cce96c8342e3ff29ac
4
- data.tar.gz: 45b8e54512221b1510ed57a9c594d2818cf4b1b86dce448145d1786422c8e788
3
+ metadata.gz: 63b5e71f6a7f803b1a270e81b5f443f41490274387873395dbcc9c05a5cdcca2
4
+ data.tar.gz: 875e34f54fd4ba0e014c91ab371be8b6d1202e908cd6470b11666e12e82577b8
5
5
  SHA512:
6
- metadata.gz: a9b61a2fcba5cdd6640b37ba99400acd45348ae4ee65d51f56b4cb3a25a180670e3b4b02a53276b68fca0e77d5c669e0a835fe7c7057df9006e8e71e7b797080
7
- data.tar.gz: 7e146be87089170ce8fd889bcfc3c055caf476f918297707d174bc86ad395db7eaafc61e3c0e49c912b90909b675a61eec35b97d0be36897f8a7bec7d9bbd4c0
6
+ metadata.gz: 06c85c6685ae41485761e725fb370688846df1b38e5097cf60222f97c7040f2b94f74d250fb37efdc8feff8dbe3b15ca8e366ff2c9f87204de36bea395ee5d2a
7
+ data.tar.gz: f5ae351e39942821b41e95a6ae17baa9536696a806847c98e693f3526345c999ef42b9babee6b25fcbae5cf79efdaebd4341c14f01f4c91c6251b8a8320c7155
data/CHANGELOG.md CHANGED
@@ -1,25 +1,39 @@
1
- #### 2.3.3
2
-
3
- - Improve keepalive handling
4
-
5
- #### 2.3.2
6
-
7
- - Allow ActiveSupport 7.0
8
-
9
- #### 2.3.1
10
-
11
- - Allow ActiveSupport 6.1
12
-
13
- #### 2.3.0
14
-
15
- - Use system's CA certificate store by default (backport from v3.2.0)
16
- To use bundled CAs instead:
17
- SomeAppName::Api.ssl_cert_bundle = :bundled
18
- On failure reading specified bundle, raises exception instead of warning
19
-
20
- #### 2.2.2
21
-
22
- - Update certs
1
+ #### 3.0.0
2
+
3
+ BREAKING CHANGES
4
+ - Update has_many, belongs_to signatures
5
+ - Rename Base#url -> #resource_path
6
+ - Drop ActiveModel <= 4.1
7
+ - `#errors` is now always an ActiveModel::Errors instance
8
+
9
+ DEPRECATION NOTICE
10
+ - ValidationError is deprecated and will be removed in 3.1.
11
+
12
+ Other changes
13
+ - Add :cache option for requests
14
+ Set default store at MyApi::Api.cache_store=
15
+ See example railtie.rb for auto-config
16
+ Examples:
17
+ SomeResource.all(cache: true)
18
+ uses MyApi::Api.cache_store
19
+ SomeResource.find(id, cache: {expires_in: 5.minutes})
20
+ uses MyApi::Api.cache_store with specified options
21
+ SomeResource.find(id, cache: Dalli::Store.new(...))
22
+ uses provided cache store (with its default options)
23
+ - Make bearer_credential_key allow strings or symbols
24
+ - Warn on attr name collision
25
+ - Update CA certificates
26
+ - Better default output for #as_json
27
+ - Allow ActiveModel/Support 6.0
28
+ - Resolve deprecation messages on Ruby 2.6
29
+ - Add #factory
30
+ - API response :errors may be hash or array
31
+ - Add RecordInvalid#errors
32
+ - Better Ruby and ActiveModel integration
33
+ - #eql?, #==, #hash
34
+ - #model_name
35
+ - #i18n_scope, config via Api.i18n_scope=
36
+ - #cache_key, #cache_version, #cache_key_with_version
23
37
 
24
38
  #### 2.2.1
25
39
 
@@ -110,4 +124,4 @@
110
124
 
111
125
  #### 1.0.0
112
126
 
113
- - Initial release
127
+ - Initial release
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014-2018 Notioneer, Inc.
1
+ Copyright (c) 2014-2020 Notioneer, Inc.
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  NCore is a Ruby gem designed to help build REST API clients. It is not an API
4
4
  client by itself, but provides several useful building blocks to build one.
5
5
 
6
- It relies on `excon` for HTTP handling and `activesupport`.
6
+ It relies on `excon` for HTTP handling and `activemodel`.
7
7
 
8
8
  If present, uses `multi_json`. Otherwise, the stdlib 'json' is used.
9
9
  'multi_json' with an accelerated json gem is recommended.
@@ -21,6 +21,8 @@ module MyApi
21
21
 
22
22
  self.strict_attributes = false
23
23
 
24
+ self.i18n_scope = :my_api
25
+
24
26
  self.instrument_key = 'request.my_api'
25
27
 
26
28
  self.status_page = 'http://my.api.status.page'
@@ -30,6 +32,12 @@ module MyApi
30
32
  # self.bearer_credential_key = :api_key
31
33
 
32
34
  self.credentials_error_message = %Q{Missing API credentials. Set default credentials using "MyApi.credentials = {api_user: YOUR_API_USER, api_key: YOUR_API_KEY}"}
35
+
36
+ # self.verify_ssl = true
37
+
38
+ # self.ssl_cert_bundle = 'path/to/bundle.crt'
39
+
40
+ # self.logger = Logger.new(STDOUT)
33
41
  end
34
42
 
35
43
  end
@@ -1,6 +1,10 @@
1
1
  module MyApi
2
2
  class Railtie < Rails::Railtie
3
3
 
4
+ config.after_initialize do
5
+ MyApi::Api.cache_store = Rails.cache
6
+ end
7
+
4
8
  initializer "my_api.log_runtime" do |app|
5
9
  require 'my_api/rails/log_subscriber'
6
10
  ActiveSupport.on_load(:action_controller) do
@@ -1,17 +1,17 @@
1
1
  module NCore
2
2
  module Associations
3
3
 
4
- def has_many(assoc, klass=nil)
4
+ def has_many(assoc, class_name: nil)
5
5
  assoc = assoc.to_s
6
- klass ||= "#{module_name}::#{assoc.camelize.singularize}"
6
+ klass = class_name || "#{module_name}::#{assoc.camelize.singularize}"
7
7
  key = "#{attrib_name}_id"
8
8
  class_eval <<-M1, __FILE__, __LINE__+1
9
9
  def #{assoc}(params={})
10
10
  return [] unless id
11
11
  reload = params.delete :reload
12
- params = parse_request_params(params).reverse_merge credentials: api_creds
13
12
  cacheable = params.except(:credentials, :request).empty?
14
- params.merge! #{key}: id
13
+ params = parse_request_params(params).reverse_merge credentials: api_creds
14
+ params[:#{key}] = id
15
15
  if cacheable
16
16
  # only cache unfiltered, default api call
17
17
  @attribs[:#{assoc}] = (!reload && @attribs[:#{assoc}]) || #{klass}.all(params)
@@ -24,7 +24,7 @@ module NCore
24
24
  def find_#{assoc.singularize}(aid, params={})
25
25
  raise UnsavedObjectError unless id
26
26
  params = parse_request_params(params).reverse_merge credentials: api_creds
27
- params.merge! #{key}: id
27
+ params[:#{key}] = id
28
28
  #{klass}.find(aid, params)
29
29
  end
30
30
  M2
@@ -33,7 +33,7 @@ module NCore
33
33
  def create_#{assoc.singularize}(params={})
34
34
  raise UnsavedObjectError unless id
35
35
  params = parse_request_params(params).reverse_merge credentials: api_creds
36
- params.merge! #{key}: id
36
+ params[:#{key}] = id
37
37
  #{klass}.create(params)
38
38
  end
39
39
  M3
@@ -42,7 +42,7 @@ module NCore
42
42
  def update_#{assoc.singularize}(aid, params={})
43
43
  raise UnsavedObjectError unless id
44
44
  params = parse_request_params(params).reverse_merge credentials: api_creds
45
- params.merge! #{key}: id
45
+ params[:#{key}] = id
46
46
  #{klass}.update(aid, params)
47
47
  end
48
48
  M4
@@ -50,7 +50,7 @@ module NCore
50
50
  def create_#{assoc.singularize}!(params={})
51
51
  raise UnsavedObjectError unless id
52
52
  params = parse_request_params(params).reverse_merge credentials: api_creds
53
- params.merge! #{key}: id
53
+ params[:#{key}] = id
54
54
  #{klass}.create!(params)
55
55
  end
56
56
  M5
@@ -58,7 +58,7 @@ module NCore
58
58
  def update_#{assoc.singularize}!(aid, params={})
59
59
  raise UnsavedObjectError unless id
60
60
  params = parse_request_params(params).reverse_merge credentials: api_creds
61
- params.merge! #{key}: id
61
+ params[:#{key}] = id
62
62
  #{klass}.update!(aid, params)
63
63
  end
64
64
  M6
@@ -67,7 +67,7 @@ module NCore
67
67
  def delete_#{assoc.singularize}(aid, params={})
68
68
  raise UnsavedObjectError unless id
69
69
  params = parse_request_params(params).reverse_merge credentials: api_creds
70
- params.merge! #{key}: id
70
+ params[:#{key}] = id
71
71
  #{klass}.delete(aid, params)
72
72
  end
73
73
  M7
@@ -75,15 +75,15 @@ module NCore
75
75
  def delete_#{assoc.singularize}!(aid, params={})
76
76
  raise UnsavedObjectError unless id
77
77
  params = parse_request_params(params).reverse_merge credentials: api_creds
78
- params.merge! #{key}: id
78
+ params[:#{key}] = id
79
79
  #{klass}.delete!(aid, params)
80
80
  end
81
81
  M8
82
82
  end
83
83
 
84
- def belongs_to(assoc, klass=nil)
84
+ def belongs_to(assoc, class_name: nil)
85
85
  assoc = assoc.to_s
86
- klass ||= "#{module_name}::#{assoc.camelize}"
86
+ klass = class_name || "#{module_name}::#{assoc.camelize}"
87
87
  class_eval <<-M1, __FILE__, __LINE__+1
88
88
  attr :#{assoc}_id
89
89
  def #{assoc}(params={})
@@ -10,6 +10,7 @@ module NCore
10
10
  module ClassMethods
11
11
  def attr(*attrs)
12
12
  attrs.each do |attr|
13
+ check_existing_method(attr)
13
14
  class_eval <<-AR, __FILE__, __LINE__+1
14
15
  def #{attr}
15
16
  self[:#{attr}]
@@ -20,6 +21,7 @@ module NCore
20
21
 
21
22
  def attr_datetime(*attrs)
22
23
  attrs.each do |attr|
24
+ check_existing_method(attr)
23
25
  class_eval <<-AD, __FILE__, __LINE__+1
24
26
  def #{attr}
25
27
  case self[:#{attr}]
@@ -39,6 +41,7 @@ module NCore
39
41
 
40
42
  def attr_decimal(*attrs)
41
43
  attrs.each do |attr|
44
+ check_existing_method(attr)
42
45
  class_eval <<-AD, __FILE__, __LINE__+1
43
46
  def #{attr}
44
47
  case self[:#{attr}]
@@ -52,10 +55,19 @@ module NCore
52
55
  end
53
56
  end
54
57
 
58
+ def check_existing_method(attr)
59
+ if method_defined?(attr) || private_method_defined?(attr)
60
+ sc = self
61
+ sc = sc.superclass while sc.superclass != Object
62
+ warn "Warning: Existing method #{sc.name}##{attr} being overwritten at #{caller[3]}"
63
+ end
64
+ end
65
+
55
66
  def parse_request_params(params={}, opts={})
56
67
  params = params.with_indifferent_access
57
68
  req = params.delete(:request)
58
69
  creds = params.delete(:credentials)
70
+ cache = params.delete(:cache)
59
71
  if opts[:json_root]
60
72
  if params.key?(opts[:json_root])
61
73
  o = params
@@ -67,6 +79,7 @@ module NCore
67
79
  end
68
80
  o[:request] = req if req
69
81
  o[:credentials] = creds if creds
82
+ o[:cache] = cache if cache
70
83
  o
71
84
  end
72
85
  end
@@ -86,23 +99,18 @@ module NCore
86
99
  creds_attr = attribs.delete(:credentials)
87
100
  @api_creds = api_creds || creds_attr
88
101
 
89
- if attribs.keys.sort == %w(data error metadata)
90
- load_attrs = attribs
91
- else
92
- load_attrs = {
93
- metadata: attribs.delete(:metadata),
94
- errors: attribs.delete(:errors),
95
- data: attribs.delete(:data) || attribs
96
- }
97
- end
98
- load(load_attrs)
102
+ load(
103
+ metadata: attribs.delete(:metadata),
104
+ errors: attribs.delete(:errors),
105
+ data: attribs.delete(:data) || attribs
106
+ )
99
107
  end
100
108
 
101
109
 
102
110
  def attributes
103
111
  Util.deep_clone(@attribs)
104
112
  end
105
-
113
+ alias_method :as_json, :attributes
106
114
 
107
115
  def [](attr)
108
116
  @attribs[attr]
@@ -150,10 +158,10 @@ module NCore
150
158
  end
151
159
 
152
160
 
153
- def load(parsed)
154
- self.metadata = parsed[:metadata] || {}.with_indifferent_access
155
- self.errors = parsed[:errors] || {}.with_indifferent_access
156
- parsed[:data].each do |k,v|
161
+ def load(data:, errors: nil, metadata: nil)
162
+ self.metadata = metadata || {}.with_indifferent_access
163
+ self.errors = parse_errors(errors)
164
+ data.each do |k,v|
157
165
  if respond_to? "#{k}="
158
166
  send "#{k}=", self.class.interpret_type(v, api_creds)
159
167
  else
@@ -163,6 +171,17 @@ module NCore
163
171
  self
164
172
  end
165
173
 
174
+ def parse_errors(errors)
175
+ errors ||= []
176
+ if errors.is_a?(::ActiveModel::Errors)
177
+ errors
178
+ else
179
+ ::ActiveModel::Errors.new(self).tap do |e0|
180
+ errors.each{|msg| e0.add :base, msg }
181
+ end
182
+ end
183
+ end
184
+
166
185
  end
167
186
 
168
187
 
data/lib/ncore/base.rb CHANGED
@@ -4,8 +4,10 @@ module NCore
4
4
 
5
5
  included do
6
6
  extend Associations
7
+ include ActiveModel
7
8
  include Attributes
8
9
  include Client
10
+ include Client::Cache
9
11
  include Identity
10
12
  include Lifecycle
11
13
  include Util
@@ -23,13 +25,13 @@ module NCore
23
25
  include Update if types.include? :update
24
26
  end
25
27
 
26
- def url
28
+ def resource_path
27
29
  class_name.underscore.pluralize
28
30
  end
29
31
  end
30
32
 
31
- def url
32
- "#{self.class.url}/#{CGI.escape((id||'-').to_s)}"
33
+ def resource_path
34
+ "#{self.class.resource_path}/#{CGI.escape((id||'-').to_s)}"
33
35
  end
34
36
 
35
37
  end
data/lib/ncore/client.rb CHANGED
@@ -6,11 +6,12 @@ module NCore
6
6
 
7
7
  module ClassMethods
8
8
 
9
- # opts - {params: {}, headers: {}, credentials: {}}
9
+ # opts - {params: {}, headers: {}, credentials: {}, cache: {}}
10
10
  # unknown keys assumed to be :params if :params is missing
11
11
  def request(method, url, opts={})
12
12
  opts = opts.with_indifferent_access
13
13
  request_credentials = opts.delete 'credentials'
14
+ cache_opts = opts.delete 'cache'
14
15
  headers = opts.delete('headers') || {}
15
16
  params = opts['params'] || opts
16
17
 
@@ -48,7 +49,7 @@ module NCore
48
49
  write_timeout: 50,
49
50
  }
50
51
 
51
- response = execute_request(rest_opts)
52
+ response = execute_request(rest_opts, cache_opts)
52
53
  parsed = parse_response(response)
53
54
  [parsed, request_credentials]
54
55
  end
@@ -58,7 +59,7 @@ module NCore
58
59
 
59
60
  def retrieve_credentials
60
61
  if credentials.blank?
61
- raise parent::Error, credentials_error_message
62
+ raise module_parent::Error, credentials_error_message
62
63
  end
63
64
  credentials
64
65
  end
@@ -69,7 +70,7 @@ module NCore
69
70
 
70
71
  def retrieve_default_url
71
72
  if default_url.blank?
72
- raise parent::Error, credentials_error_message
73
+ raise module_parent::Error, credentials_error_message
73
74
  end
74
75
  default_url
75
76
  end
@@ -87,12 +88,12 @@ module NCore
87
88
 
88
89
  def build_query_string(params)
89
90
  if params.any?
90
- query_string = params.map do |k,v|
91
+ query_string = params.sort.map do |k,v|
91
92
  if v.is_a?(Array)
92
93
  if v.empty?
93
94
  "#{k.to_s}[]="
94
95
  else
95
- v.map do |v2|
96
+ v.sort.map do |v2|
96
97
  "#{k.to_s}[]=#{CGI::escape(v2.to_s)}"
97
98
  end.join('&')
98
99
  end
@@ -163,7 +164,7 @@ module NCore
163
164
  end
164
165
 
165
166
 
166
- def execute_request(rest_opts)
167
+ def execute_request(rest_opts, _)
167
168
  debug_request rest_opts if debug
168
169
 
169
170
  tries = 0
@@ -176,7 +177,7 @@ module NCore
176
177
  tries += 1
177
178
  response = connection.request rest_opts.except(:url)
178
179
  rescue Excon::Error::Socket, Excon::Errors::SocketError, Excon::Error::Timeout,
179
- Errno::EADDRNOTAVAIL, Errno::ECONNRESET => e
180
+ Errno::EADDRNOTAVAIL => e
180
181
  # retry when keepalive was closed
181
182
  if tries <= 1 #&& e.message =~ /end of file reached/
182
183
  retry
@@ -188,30 +189,30 @@ module NCore
188
189
  debug_response response if debug
189
190
  end
190
191
  rescue Errno::ECONNRESET
191
- raise parent::ConnectionError, "Connection reset for #{host_for_error rest_opts[:url]} : check network or visit #{status_page}."
192
+ raise module_parent::ConnectionError, "Connection reset for #{host_for_error rest_opts[:url]} : check network or visit #{status_page}."
192
193
  rescue Errno::ECONNREFUSED
193
- raise parent::ConnectionError, "Connection error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
194
+ raise module_parent::ConnectionError, "Connection error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
194
195
  rescue Excon::Error::Timeout => e
195
196
  case e.message
196
197
  when /timeout reached/
197
- raise parent::ConnectionError, "Connection error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
198
+ raise module_parent::ConnectionError, "Connection error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
198
199
  else
199
200
  raise e
200
201
  end
201
202
  rescue Excon::Errors::SocketError => e
202
203
  case e.message
203
204
  when /Unable to verify certificate/
204
- raise parent::ConnectionError, "Unable to verify certificate for #{host_for_error rest_opts[:url]} : verify URL, set ssl_cert_bundle=, or disable SSL certificate verification (insecure)."
205
+ raise module_parent::ConnectionError, "Unable to verify certificate for #{host_for_error rest_opts[:url]} : verify URL or disable SSL certificate verification (insecure)."
205
206
  when /Name or service not known/, /No address associated with hostname/
206
- raise parent::ConnectionError, "DNS error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
207
+ raise module_parent::ConnectionError, "DNS error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
207
208
  when /Errno::ECONNREFUSED/
208
- raise parent::ConnectionError, "Connection error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
209
+ raise module_parent::ConnectionError, "Connection error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
209
210
  else
210
211
  raise e
211
212
  end
212
213
  rescue SocketError => e
213
214
  if e.message =~ /nodename nor servname provided/
214
- raise parent::ConnectionError, "DNS error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
215
+ raise module_parent::ConnectionError, "DNS error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
215
216
  else
216
217
  raise e
217
218
  end
@@ -219,21 +220,21 @@ module NCore
219
220
 
220
221
  case response.status
221
222
  when 401 # API auth valid; API call itself is an auth-related call and failed
222
- raise parent::AuthenticationFailed
223
+ raise module_parent::AuthenticationFailed
223
224
  when 402
224
- raise parent::AccountInactive, "Account inactive; login to portal to check account status."
225
+ raise module_parent::AccountInactive, "Account inactive; login to portal to check account status."
225
226
  when 403 # API auth failed or insufficient permissions
226
- raise parent::AccessDenied, "Access denied; check your API credentials and permissions."
227
+ raise module_parent::AccessDenied, "Access denied; check your API credentials and permissions."
227
228
  when 404
228
- raise parent::RecordNotFound
229
+ raise module_parent::RecordNotFound
229
230
  when 409, 422
230
231
  # pass through
231
232
  when 429
232
- raise parent::RateLimited
233
+ raise module_parent::RateLimited
233
234
  when 400..499
234
- raise parent::Error, "Client error: #{response.status}\n #{response.body}"
235
+ raise module_parent::Error, "Client error: #{response.status}\n #{response.body}"
235
236
  when 500..599
236
- raise parent::Error, "Server error: #{response.status}\n #{response.body}"
237
+ raise module_parent::Error, "Server error: #{response.status}\n #{response.body}"
237
238
  end
238
239
  response
239
240
  end
@@ -246,20 +247,20 @@ module NCore
246
247
  begin
247
248
  json = MultiJson.load(response.body, symbolize_keys: false) || {}
248
249
  rescue MultiJson::ParseError
249
- raise parent::Error, "Unable to parse API response; HTTP status: #{response.status}; body: #{response.body.inspect}"
250
+ raise module_parent::Error, "Unable to parse API response; HTTP status: #{response.status}; body: #{response.body.inspect}"
250
251
  end
251
252
  else
252
253
  begin
253
254
  json = JSON.parse(response.body, symbolize_names: false) || {}
254
255
  rescue JSON::ParserError
255
- raise parent::Error, "Unable to parse API response; HTTP status: #{response.status}; body: #{response.body.inspect}"
256
+ raise module_parent::Error, "Unable to parse API response; HTTP status: #{response.status}; body: #{response.body.inspect}"
256
257
  end
257
258
  end
258
259
  end
259
260
  json = json.with_indifferent_access
260
261
  errors = json.delete(:errors) || []
261
262
  if errors.any?
262
- errors = errors.values.flatten
263
+ errors = errors.values.flatten if errors.is_a?(Hash)
263
264
  metadata, json = json, {}
264
265
  else
265
266
  errors = []
@@ -296,16 +297,17 @@ module NCore
296
297
 
297
298
  def verify_ssl_cert?
298
299
  return @verify_ssl_cert unless @verify_ssl_cert.nil?
299
- if verify_ssl
300
- if ssl_cert_bundle
301
- bundle_readable = File.readable?(ssl_cert_bundle) rescue false
302
- unless bundle_readable
303
- raise parent::CertificateError, "Unable to read SSL cert bundle #{ssl_cert_bundle}."
304
- end
305
- end
300
+ bundle_readable = File.readable?(ssl_cert_bundle)
301
+ if verify_ssl && bundle_readable
306
302
  @verify_ssl_cert = true
307
303
  else
308
- m = "WARNNG: SSL cert verification is disabled. Enable verification with: #{parent}::Api.verify_ssl = true."
304
+ m = 'WARNNG: SSL cert verification is disabled.'
305
+ unless verify_ssl
306
+ m += " Enable verification with: #{module_parent}::Api.verify_ssl = true."
307
+ end
308
+ unless bundle_readable
309
+ m += " Unable to read CA bundle #{ssl_cert_bundle}."
310
+ end
309
311
  $stderr.puts m
310
312
  @verify_ssl_cert = false
311
313
  end
@@ -0,0 +1,48 @@
1
+ module NCore
2
+ module Client::Cache
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+
7
+ private
8
+
9
+ # cache_opts: true
10
+ # use *::Api.cache_store
11
+ # cache_opts: {...}
12
+ # use: *::Api.cache_store, with options: {...}
13
+ # hint: add force: true execute the query and rewrite the cache
14
+ # cache_opts: Store.new
15
+ # use Store.new as-is
16
+ def execute_request(req, cache_opts=nil)
17
+ case cache_opts
18
+ when true
19
+ store, cache_opts = cache_store, {}
20
+ when Hash
21
+ store, cache_opts = cache_store, cache_opts.symbolize_keys
22
+ when nil, false
23
+ store = false
24
+ else
25
+ store, cache_opts = cache_opts, {}
26
+ end
27
+
28
+ if store && req[:method] == :get
29
+ store.fetch request_cache_key(req.slice(:url, :headers)), cache_opts do
30
+ super
31
+ end
32
+ else
33
+ super
34
+ end
35
+ end
36
+
37
+
38
+ def request_cache_key(url:, headers:)
39
+ [ 'ncore',
40
+ url.gsub(/[^a-zA-Z0-9]+/,'-'),
41
+ Digest::MD5.hexdigest(headers.sort.to_s)
42
+ ].join ':'
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+ end
@@ -28,6 +28,9 @@ module NCore
28
28
  mattr_accessor :strict_attributes
29
29
  self.strict_attributes = true
30
30
 
31
+ mattr_accessor :i18n_scope
32
+ self.i18n_scope = :ncore
33
+
31
34
  mattr_accessor :instrument_key
32
35
  self.instrument_key = 'request.ncore'
33
36
 
@@ -37,42 +40,31 @@ module NCore
37
40
  mattr_accessor :auth_header_prefix
38
41
  self.auth_header_prefix = 'X-Api'
39
42
 
40
- mattr_accessor :bearer_credential_key
43
+ mattr_reader :bearer_credential_key
44
+ class_eval <<-MTH
45
+ def self.bearer_credential_key=(v)
46
+ @@bearer_credential_key = v&.to_s
47
+ end
48
+ def bearer_credential_key=(v)
49
+ @@bearer_credential_key = v&.to_s
50
+ end
51
+ MTH
41
52
 
42
53
  mattr_accessor :credentials_error_message
43
- self.credentials_error_message = %Q{Missing API credentials. Set default credentials using "#{self.parent.name}.credentials = {api_user: YOUR_API_USER, api_key: YOUR_API_KEY}"}
54
+ self.credentials_error_message = %Q{Missing API credentials. Set default credentials using "#{self.module_parent.name}.credentials = {api_user: YOUR_API_USER, api_key: YOUR_API_KEY}"}
44
55
 
45
56
  mattr_accessor :verify_ssl
46
57
  self.verify_ssl = true
47
58
 
48
- mattr_reader :ssl_cert_bundle
49
- class_eval <<-MTH
50
- def self.ssl_cert_bundle=(v)
51
- v = find_excon_bundle if v==:bundled
52
- @@ssl_cert_bundle = v
53
- end
54
- def ssl_cert_bundle=(v)
55
- v = find_excon_bundle if v==:bundled
56
- @@ssl_cert_bundle = v
57
- end
58
- MTH
59
+ mattr_accessor :ssl_cert_bundle
60
+ self.ssl_cert_bundle = File.dirname(__FILE__)+'/ssl/ca-certificates.crt'
61
+
62
+ mattr_accessor :cache_store
59
63
 
60
64
  mattr_accessor :logger
61
65
  self.logger = Logger.new(STDOUT)
62
66
  end
63
67
 
64
-
65
- private
66
-
67
- def find_excon_bundle
68
- b = Gem.find_files_from_load_path('../data/cacert.pem').select{|p| p=~/excon/}.first
69
- if b
70
- b.freeze
71
- else
72
- raise parent::CertificateError, 'Failed to locate CA cert bundle from excon. Specify a full path instead.'
73
- end
74
- end
75
-
76
68
  end
77
69
 
78
70
  end