api_recipes 2.6.1 → 2.8.1
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/lib/api_recipes.rb +8 -8
- data/lib/api_recipes/api.rb +4 -3
- data/lib/api_recipes/endpoint.rb +8 -1
- data/lib/api_recipes/exceptions.rb +10 -2
- data/lib/api_recipes/response.rb +1 -0
- data/lib/api_recipes/route.rb +26 -17
- data/lib/api_recipes/settings.rb +4 -2
- data/lib/api_recipes/utils.rb +31 -0
- data/lib/api_recipes/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c9d0a5a4530af3af22b9b22c091002d316e1bf7065c612d1d74f18f3aa62e37d
|
|
4
|
+
data.tar.gz: 5d322a843fa2db9cceb97cd9733b482ce17626342ad519ea036c0c821efe0d8b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6ee0d8d0c2e4c52aafa513c8619f92c1ec6b5425cf06911fc48d8d18562855cd4d0aabe96bf68985323663bdb4cb461e56b353c06431e2430a3ef9d51ecd6021
|
|
7
|
+
data.tar.gz: 4ef8593a855dd30fd21ee97642dcc5d832f7ec34218393131d1fe6758af1dbe4a8e5ad8d76f3612d289ef6e85d02a7640a65490f6b7dc103d0e32f43fbed2409
|
data/lib/api_recipes.rb
CHANGED
|
@@ -32,13 +32,13 @@ module ApiRecipes
|
|
|
32
32
|
|
|
33
33
|
define_method api_name do
|
|
34
34
|
configs = ApiRecipes._aprcps_merge_apis_configs(api_name, configs.deep_symbolize_keys)
|
|
35
|
-
api = Api.new(api_name, configs)
|
|
35
|
+
api = Api.new(api_name, configs, self)
|
|
36
36
|
ApiRecipes.copy_global_authorizations_to_api api
|
|
37
37
|
api
|
|
38
38
|
end
|
|
39
39
|
define_singleton_method api_name do
|
|
40
40
|
configs = ApiRecipes._aprcps_merge_apis_configs(api_name, configs.deep_symbolize_keys)
|
|
41
|
-
api = Api.new(api_name, configs)
|
|
41
|
+
api = Api.new(api_name, configs, self)
|
|
42
42
|
ApiRecipes.copy_global_authorizations_to_api api
|
|
43
43
|
api
|
|
44
44
|
end
|
|
@@ -58,6 +58,7 @@ module ApiRecipes
|
|
|
58
58
|
unless @configuration
|
|
59
59
|
@configuration = Configuration.new
|
|
60
60
|
end
|
|
61
|
+
|
|
61
62
|
@configuration
|
|
62
63
|
end
|
|
63
64
|
|
|
@@ -105,7 +106,7 @@ module ApiRecipes
|
|
|
105
106
|
def self._aprcps_define_global_apis
|
|
106
107
|
configuration.apis_configs.each do |api_name, api_configs|
|
|
107
108
|
api_name = api_name.to_sym
|
|
108
|
-
_aprcps_global_storage[api_name] = Api.new api_name, api_configs
|
|
109
|
+
_aprcps_global_storage[api_name] = Api.new api_name, api_configs, self
|
|
109
110
|
define_singleton_method api_name do
|
|
110
111
|
_aprcps_global_storage[api_name]
|
|
111
112
|
end
|
|
@@ -116,6 +117,7 @@ module ApiRecipes
|
|
|
116
117
|
unless @storage
|
|
117
118
|
@storage = {}
|
|
118
119
|
end
|
|
120
|
+
|
|
119
121
|
@storage
|
|
120
122
|
end
|
|
121
123
|
|
|
@@ -130,11 +132,9 @@ module ApiRecipes
|
|
|
130
132
|
unless api_name.is_a?(String) || api_name.is_a?(Symbol)
|
|
131
133
|
raise ArgumentError, "no api_name provided. Given: #{api_name.inspect}"
|
|
132
134
|
end
|
|
133
|
-
|
|
134
|
-
ApiRecipes.configuration.apis_configs[api_name] = {}
|
|
135
|
-
end
|
|
135
|
+
global_api_configs = _aprcps_global_storage[api_name]&.configs || {}
|
|
136
136
|
if configs
|
|
137
|
-
|
|
137
|
+
global_api_configs.deep_merge(configs) do |_, old_val, new_val|
|
|
138
138
|
if new_val.nil?
|
|
139
139
|
old_val
|
|
140
140
|
else
|
|
@@ -142,7 +142,7 @@ module ApiRecipes
|
|
|
142
142
|
end
|
|
143
143
|
end
|
|
144
144
|
else
|
|
145
|
-
|
|
145
|
+
global_api_configs
|
|
146
146
|
end
|
|
147
147
|
end
|
|
148
148
|
end
|
data/lib/api_recipes/api.rb
CHANGED
|
@@ -2,13 +2,14 @@ module ApiRecipes
|
|
|
2
2
|
class Api
|
|
3
3
|
|
|
4
4
|
attr_accessor :name, :configs, :authorization, :basic_auth
|
|
5
|
-
attr_reader :base_configs
|
|
5
|
+
attr_reader :base_configs, :object
|
|
6
6
|
|
|
7
|
-
BASE_CONFIGS_KEYS = [:protocol, :host, :port, :api_version, :timeout, :on_bad_code]
|
|
7
|
+
BASE_CONFIGS_KEYS = [:protocol, :host, :port, :api_version, :timeout, :on_bad_code, :verify_with]
|
|
8
8
|
|
|
9
|
-
def initialize(name, configs)
|
|
9
|
+
def initialize(name, configs, object)
|
|
10
10
|
@name = name
|
|
11
11
|
@configs = ApiRecipes::Settings::DEFAULT.merge configs
|
|
12
|
+
@object = object
|
|
12
13
|
|
|
13
14
|
# Generate some_api.some_endpoint methods
|
|
14
15
|
# e.g. github.users
|
data/lib/api_recipes/endpoint.rb
CHANGED
|
@@ -3,6 +3,8 @@ module ApiRecipes
|
|
|
3
3
|
|
|
4
4
|
attr_reader :api, :name, :params, :route, :children
|
|
5
5
|
|
|
6
|
+
FORWARDABLE_PARAMS = %i[verify_with].freeze
|
|
7
|
+
|
|
6
8
|
def initialize(api: nil, name: nil, path: nil, params: {}, request_params: [], &block)
|
|
7
9
|
@api = api
|
|
8
10
|
@name = name
|
|
@@ -52,6 +54,8 @@ module ApiRecipes
|
|
|
52
54
|
# puts "generating children of #{@name}: #{children.inspect}"
|
|
53
55
|
if children
|
|
54
56
|
children.each do |ep_name, pars|
|
|
57
|
+
pars = forwardable_params.merge(pars) if pars
|
|
58
|
+
# TODO: Merge pars with params
|
|
55
59
|
# puts "Creating Endpoint '#{@name}' child '#{ep_name}' passing path #{build_path}"
|
|
56
60
|
define_singleton_method ep_name do |*request_params, &block|
|
|
57
61
|
Endpoint.new api: @api, name: ep_name, path: build_path, params: pars, request_params: request_params, &block
|
|
@@ -89,7 +93,6 @@ module ApiRecipes
|
|
|
89
93
|
end
|
|
90
94
|
# Merge DEFAULT_ROUTE_ATTRIBUTES with Api base_configs
|
|
91
95
|
# Then merge the result with provided attributes
|
|
92
|
-
|
|
93
96
|
@params = Settings::DEFAULT_ROUTE_ATTRIBUTES.inject({}) do |out, key_val|
|
|
94
97
|
new_val = @api.base_configs[key_val.first]
|
|
95
98
|
out[key_val.first] = new_val.nil? ? key_val.last : new_val
|
|
@@ -126,5 +129,9 @@ module ApiRecipes
|
|
|
126
129
|
def required_params_for_path
|
|
127
130
|
absolute_path.scan(/:(\w+)/).flatten.map { |p| p.to_sym }
|
|
128
131
|
end
|
|
132
|
+
|
|
133
|
+
def forwardable_params
|
|
134
|
+
params.select { |k, v| FORWARDABLE_PARAMS.include? k }
|
|
135
|
+
end
|
|
129
136
|
end
|
|
130
137
|
end
|
|
@@ -40,8 +40,16 @@ module ApiRecipes
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
class ResponseCodeNotAsExpected < Exception
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
|
|
44
|
+
attr_reader :path, :expected_code, :response
|
|
45
|
+
|
|
46
|
+
def initialize(path, expected_code = nil, response = nil, message: nil)
|
|
47
|
+
@path = path
|
|
48
|
+
@expected_code = expected_code
|
|
49
|
+
@response = response
|
|
50
|
+
unless message
|
|
51
|
+
message = "response code for request on route '#{@path}' has returned '#{@response.code}', but '#{@expected_code}' was expected\n\nResponse body:\n #{@response.body}"
|
|
52
|
+
end
|
|
45
53
|
super(message)
|
|
46
54
|
end
|
|
47
55
|
end
|
data/lib/api_recipes/response.rb
CHANGED
data/lib/api_recipes/route.rb
CHANGED
|
@@ -43,31 +43,40 @@ module ApiRecipes
|
|
|
43
43
|
|
|
44
44
|
def build_url_from_path
|
|
45
45
|
attrs = {
|
|
46
|
-
scheme: settings[:protocol],
|
|
46
|
+
scheme: settings[:protocol].to_s,
|
|
47
47
|
host: settings[:host],
|
|
48
48
|
port: port,
|
|
49
|
-
path:
|
|
49
|
+
path: path
|
|
50
50
|
}
|
|
51
|
-
URI::Generic.
|
|
51
|
+
URI::Generic.build2 attrs
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def check_response_code
|
|
55
|
-
# If :ok_code property is present, check the response code
|
|
56
55
|
ok_code = false
|
|
57
56
|
code = @response.code
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
message = nil
|
|
58
|
+
|
|
59
|
+
verify_with = attributes[:verify_with]
|
|
60
|
+
if verify_with && @api.object.respond_to?(verify_with, true )
|
|
61
|
+
ok_code = @api.object.send verify_with, @response
|
|
62
|
+
message = "response for request on route '#{path}' was not valid. Verified with #{@api.object}##{verify_with}.\n\nResponse body:\n #{@response.body}"
|
|
61
63
|
else
|
|
62
|
-
#
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
# If :ok_code property is present, check the response code
|
|
65
|
+
if expected_code = attributes[:ok_code]
|
|
66
|
+
# If the code does not match, apply the requested strategy
|
|
67
|
+
ok_code = true if code == expected_code
|
|
68
|
+
else
|
|
69
|
+
# Default: 200 <= OK < 300
|
|
70
|
+
ok_code = true if @response.status.success?
|
|
71
|
+
expected_code = '200 <= CODE < 300'
|
|
72
|
+
end
|
|
65
73
|
end
|
|
74
|
+
|
|
66
75
|
unless ok_code
|
|
67
76
|
case attributes[:on_bad_code].to_s
|
|
68
77
|
when 'ignore'
|
|
69
78
|
when 'raise'
|
|
70
|
-
raise ResponseCodeNotAsExpected.new(path, expected_code,
|
|
79
|
+
raise ResponseCodeNotAsExpected.new(path, expected_code, @response, message: message)
|
|
71
80
|
end
|
|
72
81
|
end
|
|
73
82
|
end
|
|
@@ -81,12 +90,12 @@ module ApiRecipes
|
|
|
81
90
|
end
|
|
82
91
|
|
|
83
92
|
def port
|
|
84
|
-
settings[:port] || case settings[:protocol]
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
93
|
+
settings[:port].to_s || case settings[:protocol].to_s
|
|
94
|
+
when 'http'
|
|
95
|
+
'80'
|
|
96
|
+
when 'https'
|
|
97
|
+
'443'
|
|
98
|
+
end
|
|
90
99
|
end
|
|
91
100
|
|
|
92
101
|
def prepare_request
|
data/lib/api_recipes/settings.rb
CHANGED
|
@@ -9,7 +9,8 @@ module ApiRecipes
|
|
|
9
9
|
base_url: nil,
|
|
10
10
|
timeout: 3,
|
|
11
11
|
on_bad_code: 'raise',
|
|
12
|
-
endpoints: {}
|
|
12
|
+
endpoints: {},
|
|
13
|
+
verify_with: nil
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
DEFAULT_ROUTE_ATTRIBUTES = {
|
|
@@ -18,7 +19,8 @@ module ApiRecipes
|
|
|
18
19
|
path: nil,
|
|
19
20
|
ok_code: nil,
|
|
20
21
|
timeout: DEFAULT[:timeout],
|
|
21
|
-
on_bad_code: DEFAULT[:on_bad_code]
|
|
22
|
+
on_bad_code: DEFAULT[:on_bad_code],
|
|
23
|
+
verify_with: DEFAULT[:verify_with]
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
AVAILABLE_PARAMS_ENCODINGS = %w(form params json body)
|
data/lib/api_recipes/utils.rb
CHANGED
|
@@ -77,6 +77,37 @@ class Hash
|
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
+
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
|
81
|
+
#
|
|
82
|
+
# h1 = { a: true, b: { c: [1, 2, 3] } }
|
|
83
|
+
# h2 = { a: false, b: { x: [3, 4, 5] } }
|
|
84
|
+
#
|
|
85
|
+
# h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
|
|
86
|
+
#
|
|
87
|
+
# Like with Hash#merge in the standard library, a block can be provided
|
|
88
|
+
# to merge values:
|
|
89
|
+
#
|
|
90
|
+
# h1 = { a: 100, b: 200, c: { c1: 100 } }
|
|
91
|
+
# h2 = { b: 250, c: { c1: 200 } }
|
|
92
|
+
# h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val }
|
|
93
|
+
# # => { a: 100, b: 450, c: { c1: 300 } }
|
|
94
|
+
def deep_merge(other_hash, &block)
|
|
95
|
+
dup.deep_merge!(other_hash, &block)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Same as +deep_merge+, but modifies +self+.
|
|
99
|
+
def deep_merge!(other_hash, &block)
|
|
100
|
+
merge!(other_hash) do |key, this_val, other_val|
|
|
101
|
+
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
|
102
|
+
this_val.deep_merge(other_val, &block)
|
|
103
|
+
elsif block_given?
|
|
104
|
+
block.call(key, this_val, other_val)
|
|
105
|
+
else
|
|
106
|
+
other_val
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
80
111
|
# Returns a new hash with all keys converted by the block operation.
|
|
81
112
|
# This includes the keys from the root hash and from all
|
|
82
113
|
# nested hashes and arrays.
|
data/lib/api_recipes/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: api_recipes
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.8.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alessandro Verlato
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-02-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: http
|