ncore 2.2.0 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +57 -1
- data/LICENSE +1 -1
- data/README.md +1 -1
- data/example/lib/my_api/api_config.rb +10 -0
- data/example/lib/my_api/rails/railtie.rb +4 -0
- data/lib/ncore.rb +31 -3
- data/lib/ncore/associations.rb +13 -13
- data/lib/ncore/attributes.rb +36 -17
- data/lib/ncore/base.rb +6 -3
- data/lib/ncore/client.rb +35 -34
- data/lib/ncore/client_cache.rb +48 -0
- data/lib/ncore/configuration.rb +38 -4
- data/lib/ncore/exceptions.rb +8 -1
- data/lib/ncore/identity.rb +27 -0
- data/lib/ncore/lifecycle.rb +3 -3
- data/lib/ncore/methods/all.rb +3 -7
- data/lib/ncore/methods/build.rb +2 -2
- data/lib/ncore/methods/count.rb +1 -1
- data/lib/ncore/methods/create.rb +4 -5
- data/lib/ncore/methods/delete.rb +6 -7
- data/lib/ncore/methods/delete_bulk.rb +4 -4
- data/lib/ncore/methods/delete_single.rb +4 -5
- data/lib/ncore/methods/find.rb +5 -6
- data/lib/ncore/methods/find_single.rb +5 -9
- data/lib/ncore/methods/update.rb +6 -7
- data/lib/ncore/methods/update_bulk.rb +26 -0
- data/lib/ncore/rails/active_model.rb +24 -14
- data/lib/ncore/rails/module_fix.rb +5 -3
- data/lib/ncore/singleton_base.rb +4 -3
- data/lib/ncore/util.rb +10 -2
- data/lib/ncore/version.rb +1 -1
- data/ncore.gemspec +1 -1
- metadata +11 -10
- data/lib/ncore/ssl/ca-certificates.crt +0 -4027
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79a7f509e1857cf0a4acd6392c2226e9be22b1b55753b63780b58d28651dade5
|
4
|
+
data.tar.gz: 85a06a908f8926eac01bebd0d672e57f43ca57ecd05723f3e565d0181998e2d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bf6ddb6c01d38f030566468df96d9027ba57ae3265ffa7974e89cf5645230ccd4691892fbf77fddaded5bf61d005c2a601af7ad4fec83ce6acc8d471875e9cf
|
7
|
+
data.tar.gz: e70acae56b27d08249ad2b923d52a0e695323f28a83cf02b5adff2a54d1ee316b2c0de48d9afbbc8dca15f2495e19206ba7b4a910278bd7cec3ca15152d84b89
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,59 @@
|
|
1
|
+
#### 3.2.0
|
2
|
+
|
3
|
+
- Use system's CA certificate store by default
|
4
|
+
To use bundled CAs instead:
|
5
|
+
SomeAppName::Api.ssl_cert_bundle = :bundled
|
6
|
+
On failure reading specified bundle, raises exception instead of warning
|
7
|
+
|
8
|
+
#### 3.1.0
|
9
|
+
|
10
|
+
- Add .bulk_update and bulk_update!
|
11
|
+
|
12
|
+
#### 3.0.0
|
13
|
+
|
14
|
+
BREAKING CHANGES
|
15
|
+
- Update has_many, belongs_to signatures
|
16
|
+
- Rename Base#url -> #resource_path
|
17
|
+
- Drop ActiveModel <= 4.1
|
18
|
+
- `#errors` is now always an ActiveModel::Errors instance
|
19
|
+
|
20
|
+
DEPRECATION NOTICE
|
21
|
+
- ValidationError is deprecated and will be removed in 3.1.
|
22
|
+
|
23
|
+
Other changes
|
24
|
+
- Add :cache option for requests
|
25
|
+
Set default store at MyApi::Api.cache_store=
|
26
|
+
See example railtie.rb for auto-config
|
27
|
+
Examples:
|
28
|
+
SomeResource.all(cache: true)
|
29
|
+
uses MyApi::Api.cache_store
|
30
|
+
SomeResource.find(id, cache: {expires_in: 5.minutes})
|
31
|
+
uses MyApi::Api.cache_store with specified options
|
32
|
+
SomeResource.find(id, cache: Dalli::Store.new(...))
|
33
|
+
uses provided cache store (with its default options)
|
34
|
+
- Make bearer_credential_key allow strings or symbols
|
35
|
+
- Warn on attr name collision
|
36
|
+
- Update CA certificates
|
37
|
+
- Better default output for #as_json
|
38
|
+
- Allow ActiveModel/Support 6.0
|
39
|
+
- Resolve deprecation messages on Ruby 2.6
|
40
|
+
- Add #factory
|
41
|
+
- API response :errors may be hash or array
|
42
|
+
- Add RecordInvalid#errors
|
43
|
+
- Better Ruby and ActiveModel integration
|
44
|
+
- #eql?, #==, #hash
|
45
|
+
- #model_name
|
46
|
+
- #i18n_scope, config via Api.i18n_scope=
|
47
|
+
- #cache_key, #cache_version, #cache_key_with_version
|
48
|
+
|
49
|
+
#### 2.2.2
|
50
|
+
|
51
|
+
- Update certs
|
52
|
+
|
53
|
+
#### 2.2.1
|
54
|
+
|
55
|
+
- Fix decimal attributes on Ruby <= 2.5.x
|
56
|
+
|
1
57
|
#### 2.2.0
|
2
58
|
|
3
59
|
- Allow ActiveSupport 6.0
|
@@ -83,4 +139,4 @@
|
|
83
139
|
|
84
140
|
#### 1.0.0
|
85
141
|
|
86
|
-
- Initial release
|
142
|
+
- Initial release
|
data/LICENSE
CHANGED
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 `
|
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,14 @@ 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
|
+
# Uses system/OS bundle by default
|
39
|
+
# self.ssl_cert_bundle = :bundled # uses excon's included bundle
|
40
|
+
# self.ssl_cert_bundle = 'path/to/bundle.crt'
|
41
|
+
|
42
|
+
# self.logger = Logger.new(STDOUT)
|
33
43
|
end
|
34
44
|
|
35
45
|
end
|
data/lib/ncore.rb
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
require 'active_support/all'
|
2
|
+
require 'active_model'
|
2
3
|
require 'excon'
|
3
4
|
require 'pp'
|
4
5
|
|
5
|
-
%w(
|
6
|
+
%w(
|
7
|
+
version
|
8
|
+
builder
|
9
|
+
configuration
|
10
|
+
associations
|
11
|
+
attributes
|
12
|
+
client
|
13
|
+
client_cache
|
14
|
+
collection
|
15
|
+
exceptions
|
16
|
+
identity
|
17
|
+
lifecycle
|
18
|
+
util
|
19
|
+
base
|
20
|
+
singleton_base
|
21
|
+
).each do |f|
|
6
22
|
require "ncore/#{f}"
|
7
23
|
end
|
8
24
|
|
9
|
-
%w(
|
25
|
+
%w(
|
26
|
+
all
|
27
|
+
build
|
28
|
+
count
|
29
|
+
create
|
30
|
+
delete
|
31
|
+
delete_bulk
|
32
|
+
delete_single
|
33
|
+
find
|
34
|
+
find_single
|
35
|
+
update
|
36
|
+
update_bulk
|
37
|
+
).each do |f|
|
10
38
|
require "ncore/methods/#{f}"
|
11
39
|
end
|
12
40
|
|
13
41
|
require 'ncore/rails/action_controller' if defined?(::ActionController)
|
14
|
-
require 'ncore/rails/active_model'
|
42
|
+
require 'ncore/rails/active_model'
|
15
43
|
require 'ncore/rails/module_fix'
|
data/lib/ncore/associations.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
module NCore
|
2
2
|
module Associations
|
3
3
|
|
4
|
-
def has_many(assoc,
|
4
|
+
def has_many(assoc, class_name: nil)
|
5
5
|
assoc = assoc.to_s
|
6
|
-
klass
|
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.
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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,
|
84
|
+
def belongs_to(assoc, class_name: nil)
|
85
85
|
assoc = assoc.to_s
|
86
|
-
klass
|
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={})
|
data/lib/ncore/attributes.rb
CHANGED
@@ -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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
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(
|
154
|
-
self.metadata =
|
155
|
-
self.errors =
|
156
|
-
|
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,13 +171,24 @@ 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
|
|
169
188
|
class BigMoney < SimpleDelegator
|
170
189
|
|
171
|
-
def initialize(*args
|
172
|
-
__setobj__(BigDecimal(*args
|
190
|
+
def initialize(*args)
|
191
|
+
__setobj__(BigDecimal(*args))
|
173
192
|
end
|
174
193
|
|
175
194
|
def to_s
|
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
|
@@ -21,15 +23,16 @@ module NCore
|
|
21
23
|
include DeleteBulk if types.include? :delete_bulk
|
22
24
|
include Find if types.include? :find
|
23
25
|
include Update if types.include? :update
|
26
|
+
include UpdateBulk if types.include? :update_bulk
|
24
27
|
end
|
25
28
|
|
26
|
-
def
|
29
|
+
def resource_path
|
27
30
|
class_name.underscore.pluralize
|
28
31
|
end
|
29
32
|
end
|
30
33
|
|
31
|
-
def
|
32
|
-
"#{self.class.
|
34
|
+
def resource_path
|
35
|
+
"#{self.class.resource_path}/#{CGI.escape((id||'-').to_s)}"
|
33
36
|
end
|
34
37
|
|
35
38
|
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
|
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
|
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
|
@@ -175,7 +176,8 @@ module NCore
|
|
175
176
|
begin
|
176
177
|
tries += 1
|
177
178
|
response = connection.request rest_opts.except(:url)
|
178
|
-
rescue Excon::Errors::SocketError, Excon::Error::Timeout,
|
179
|
+
rescue Excon::Error::Socket, Excon::Errors::SocketError, Excon::Error::Timeout,
|
180
|
+
Errno::EADDRNOTAVAIL => e
|
179
181
|
# retry when keepalive was closed
|
180
182
|
if tries <= 1 #&& e.message =~ /end of file reached/
|
181
183
|
retry
|
@@ -187,30 +189,30 @@ module NCore
|
|
187
189
|
debug_response response if debug
|
188
190
|
end
|
189
191
|
rescue Errno::ECONNRESET
|
190
|
-
raise
|
192
|
+
raise module_parent::ConnectionError, "Connection reset for #{host_for_error rest_opts[:url]} : check network or visit #{status_page}."
|
191
193
|
rescue Errno::ECONNREFUSED
|
192
|
-
raise
|
194
|
+
raise module_parent::ConnectionError, "Connection error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
|
193
195
|
rescue Excon::Error::Timeout => e
|
194
196
|
case e.message
|
195
197
|
when /timeout reached/
|
196
|
-
raise
|
198
|
+
raise module_parent::ConnectionError, "Connection error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
|
197
199
|
else
|
198
200
|
raise e
|
199
201
|
end
|
200
202
|
rescue Excon::Errors::SocketError => e
|
201
203
|
case e.message
|
202
204
|
when /Unable to verify certificate/
|
203
|
-
raise
|
205
|
+
raise module_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)."
|
204
206
|
when /Name or service not known/, /No address associated with hostname/
|
205
|
-
raise
|
207
|
+
raise module_parent::ConnectionError, "DNS error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
|
206
208
|
when /Errno::ECONNREFUSED/
|
207
|
-
raise
|
209
|
+
raise module_parent::ConnectionError, "Connection error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
|
208
210
|
else
|
209
211
|
raise e
|
210
212
|
end
|
211
213
|
rescue SocketError => e
|
212
214
|
if e.message =~ /nodename nor servname provided/
|
213
|
-
raise
|
215
|
+
raise module_parent::ConnectionError, "DNS error for #{host_for_error rest_opts[:url]} : check network and DNS or visit #{status_page}."
|
214
216
|
else
|
215
217
|
raise e
|
216
218
|
end
|
@@ -218,21 +220,21 @@ module NCore
|
|
218
220
|
|
219
221
|
case response.status
|
220
222
|
when 401 # API auth valid; API call itself is an auth-related call and failed
|
221
|
-
raise
|
223
|
+
raise module_parent::AuthenticationFailed
|
222
224
|
when 402
|
223
|
-
raise
|
225
|
+
raise module_parent::AccountInactive, "Account inactive; login to portal to check account status."
|
224
226
|
when 403 # API auth failed or insufficient permissions
|
225
|
-
raise
|
227
|
+
raise module_parent::AccessDenied, "Access denied; check your API credentials and permissions."
|
226
228
|
when 404
|
227
|
-
raise
|
229
|
+
raise module_parent::RecordNotFound
|
228
230
|
when 409, 422
|
229
231
|
# pass through
|
230
232
|
when 429
|
231
|
-
raise
|
233
|
+
raise module_parent::RateLimited
|
232
234
|
when 400..499
|
233
|
-
raise
|
235
|
+
raise module_parent::Error, "Client error: #{response.status}\n #{response.body}"
|
234
236
|
when 500..599
|
235
|
-
raise
|
237
|
+
raise module_parent::Error, "Server error: #{response.status}\n #{response.body}"
|
236
238
|
end
|
237
239
|
response
|
238
240
|
end
|
@@ -245,20 +247,20 @@ module NCore
|
|
245
247
|
begin
|
246
248
|
json = MultiJson.load(response.body, symbolize_keys: false) || {}
|
247
249
|
rescue MultiJson::ParseError
|
248
|
-
raise
|
250
|
+
raise module_parent::Error, "Unable to parse API response; HTTP status: #{response.status}; body: #{response.body.inspect}"
|
249
251
|
end
|
250
252
|
else
|
251
253
|
begin
|
252
254
|
json = JSON.parse(response.body, symbolize_names: false) || {}
|
253
255
|
rescue JSON::ParserError
|
254
|
-
raise
|
256
|
+
raise module_parent::Error, "Unable to parse API response; HTTP status: #{response.status}; body: #{response.body.inspect}"
|
255
257
|
end
|
256
258
|
end
|
257
259
|
end
|
258
260
|
json = json.with_indifferent_access
|
259
261
|
errors = json.delete(:errors) || []
|
260
262
|
if errors.any?
|
261
|
-
errors = errors.values.flatten
|
263
|
+
errors = errors.values.flatten if errors.is_a?(Hash)
|
262
264
|
metadata, json = json, {}
|
263
265
|
else
|
264
266
|
errors = []
|
@@ -295,17 +297,16 @@ module NCore
|
|
295
297
|
|
296
298
|
def verify_ssl_cert?
|
297
299
|
return @verify_ssl_cert unless @verify_ssl_cert.nil?
|
298
|
-
|
299
|
-
|
300
|
+
if verify_ssl
|
301
|
+
if ssl_cert_bundle
|
302
|
+
bundle_readable = File.readable?(ssl_cert_bundle) rescue false
|
303
|
+
unless bundle_readable
|
304
|
+
raise module_parent::CertificateError, "Unable to read SSL cert bundle #{ssl_cert_bundle}."
|
305
|
+
end
|
306
|
+
end
|
300
307
|
@verify_ssl_cert = true
|
301
308
|
else
|
302
|
-
m =
|
303
|
-
unless verify_ssl
|
304
|
-
m += " Enable verification with: #{parent}::Api.verify_ssl = true."
|
305
|
-
end
|
306
|
-
unless bundle_readable
|
307
|
-
m += " Unable to read CA bundle #{ssl_cert_bundle}."
|
308
|
-
end
|
309
|
+
m = "WARNNG: SSL cert verification is disabled. Enable verification with: #{module_parent}::Api.verify_ssl = true."
|
309
310
|
$stderr.puts m
|
310
311
|
@verify_ssl_cert = false
|
311
312
|
end
|