restful_client 0.1.0 → 0.3.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/.hound.yml +2 -0
- data/.ruby-style.yml +239 -0
- data/.travis.yml +5 -0
- data/Gemfile +2 -1
- data/README.md +10 -10
- data/lib/restful_client.rb +57 -46
- data/lib/restful_client_configuration.rb +12 -14
- data/lib/restful_client_logger.rb +6 -5
- data/lib/restful_client_uri.rb +0 -1
- data/restful_client.gemspec +4 -7
- data/spec/restful_client_spec.rb +191 -160
- data/spec/spec_helper.rb +1 -1
- data/spec/support/test_server.rb +19 -17
- metadata +6 -18
- data/lib/restful_client/version.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ffdd1539730f64064b5e045bf4afcad0374ec2dc
|
4
|
+
data.tar.gz: 3110fcd87794defb963f4214b8164e706bf1cea5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b432086f2e3598fae207ca1a85e56a7c3a74f69194d00b10aa9ed495737c8072452e08d9f0e2c4ef97ff0b0899216400215e350832eb09461b4999013d4510e
|
7
|
+
data.tar.gz: 6aebfaf5672c02e41a1b66d7c884bd0c7c3a404a4b9a678d014ef0f0fef9ae194a46868f69c5a9d4cec2bd078c9eeeab99710dde7d04e49d5f61df336a3000e6
|
data/.hound.yml
ADDED
data/.ruby-style.yml
ADDED
@@ -0,0 +1,239 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- "vendor/**/*"
|
4
|
+
- "db/schema.rb"
|
5
|
+
UseCache: false
|
6
|
+
Style/CollectionMethods:
|
7
|
+
Description: Preferred collection methods.
|
8
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#map-find-select-reduce-size
|
9
|
+
Enabled: true
|
10
|
+
PreferredMethods:
|
11
|
+
collect: map
|
12
|
+
collect!: map!
|
13
|
+
find: detect
|
14
|
+
find_all: select
|
15
|
+
reduce: inject
|
16
|
+
Style/DotPosition:
|
17
|
+
Description: Checks the position of the dot in multi-line method calls.
|
18
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains
|
19
|
+
Enabled: true
|
20
|
+
EnforcedStyle: trailing
|
21
|
+
SupportedStyles:
|
22
|
+
- leading
|
23
|
+
- trailing
|
24
|
+
Style/FileName:
|
25
|
+
Description: Use snake_case for source file names.
|
26
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#snake-case-files
|
27
|
+
Enabled: false
|
28
|
+
Exclude: []
|
29
|
+
Style/GuardClause:
|
30
|
+
Description: Check for conditionals that can be replaced with guard clauses
|
31
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals
|
32
|
+
Enabled: false
|
33
|
+
MinBodyLength: 1
|
34
|
+
Style/IfUnlessModifier:
|
35
|
+
Description: Favor modifier if/unless usage when you have a single-line body.
|
36
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier
|
37
|
+
Enabled: false
|
38
|
+
MaxLineLength: 80
|
39
|
+
Style/OptionHash:
|
40
|
+
Description: Don't use option hashes when you can use keyword arguments.
|
41
|
+
Enabled: false
|
42
|
+
Style/PercentLiteralDelimiters:
|
43
|
+
Description: Use `%`-literal delimiters consistently
|
44
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-literal-braces
|
45
|
+
Enabled: false
|
46
|
+
PreferredDelimiters:
|
47
|
+
"%": "()"
|
48
|
+
"%i": "()"
|
49
|
+
"%q": "()"
|
50
|
+
"%Q": "()"
|
51
|
+
"%r": "{}"
|
52
|
+
"%s": "()"
|
53
|
+
"%w": "()"
|
54
|
+
"%W": "()"
|
55
|
+
"%x": "()"
|
56
|
+
Style/PredicateName:
|
57
|
+
Description: Check the names of predicate methods.
|
58
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark
|
59
|
+
Enabled: true
|
60
|
+
NamePrefix:
|
61
|
+
- is_
|
62
|
+
- has_
|
63
|
+
- have_
|
64
|
+
NamePrefixBlacklist:
|
65
|
+
- is_
|
66
|
+
Exclude:
|
67
|
+
- spec/**/*
|
68
|
+
Style/RaiseArgs:
|
69
|
+
Description: Checks the arguments passed to raise/fail.
|
70
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#exception-class-messages
|
71
|
+
Enabled: false
|
72
|
+
EnforcedStyle: exploded
|
73
|
+
SupportedStyles:
|
74
|
+
- compact
|
75
|
+
- exploded
|
76
|
+
Style/SignalException:
|
77
|
+
Description: Checks for proper usage of fail and raise.
|
78
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#fail-method
|
79
|
+
Enabled: false
|
80
|
+
EnforcedStyle: semantic
|
81
|
+
SupportedStyles:
|
82
|
+
- only_raise
|
83
|
+
- only_fail
|
84
|
+
- semantic
|
85
|
+
Style/SingleLineBlockParams:
|
86
|
+
Description: Enforces the names of some block params.
|
87
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#reduce-blocks
|
88
|
+
Enabled: false
|
89
|
+
Methods:
|
90
|
+
- reduce:
|
91
|
+
- a
|
92
|
+
- e
|
93
|
+
- inject:
|
94
|
+
- a
|
95
|
+
- e
|
96
|
+
Style/SingleLineMethods:
|
97
|
+
Description: Avoid single-line methods.
|
98
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-single-line-methods
|
99
|
+
Enabled: false
|
100
|
+
AllowIfMethodIsEmpty: true
|
101
|
+
Style/StringLiterals:
|
102
|
+
Description: Checks if uses of quotes match the configured preference.
|
103
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-string-literals
|
104
|
+
Enabled: false
|
105
|
+
EnforcedStyle: double_quotes
|
106
|
+
SupportedStyles:
|
107
|
+
- single_quotes
|
108
|
+
- double_quotes
|
109
|
+
Style/StringLiteralsInInterpolation:
|
110
|
+
Description: Checks if uses of quotes inside expressions in interpolated strings
|
111
|
+
match the configured preference.
|
112
|
+
Enabled: true
|
113
|
+
EnforcedStyle: single_quotes
|
114
|
+
SupportedStyles:
|
115
|
+
- single_quotes
|
116
|
+
- double_quotes
|
117
|
+
Style/TrailingComma:
|
118
|
+
Description: Checks for trailing comma in parameter lists and literals.
|
119
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas
|
120
|
+
Enabled: false
|
121
|
+
EnforcedStyleForMultiline: no_comma
|
122
|
+
SupportedStyles:
|
123
|
+
- comma
|
124
|
+
- no_comma
|
125
|
+
Metrics/AbcSize:
|
126
|
+
Description: A calculated magnitude based on number of assignments, branches, and
|
127
|
+
conditions.
|
128
|
+
Enabled: false
|
129
|
+
Max: 15
|
130
|
+
Metrics/ClassLength:
|
131
|
+
Description: Avoid classes longer than 100 lines of code.
|
132
|
+
Enabled: false
|
133
|
+
CountComments: false
|
134
|
+
Max: 100
|
135
|
+
Metrics/LineLength:
|
136
|
+
Max: 130
|
137
|
+
Metrics/ModuleLength:
|
138
|
+
CountComments: false
|
139
|
+
Max: 100
|
140
|
+
Description: Avoid modules longer than 100 lines of code.
|
141
|
+
Enabled: false
|
142
|
+
Metrics/CyclomaticComplexity:
|
143
|
+
Description: A complexity metric that is strongly correlated to the number of test
|
144
|
+
cases needed to validate a method.
|
145
|
+
Enabled: false
|
146
|
+
Max: 6
|
147
|
+
Metrics/MethodLength:
|
148
|
+
Description: Avoid methods longer than 10 lines of code.
|
149
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#short-methods
|
150
|
+
Enabled: false
|
151
|
+
CountComments: false
|
152
|
+
Max: 10
|
153
|
+
Metrics/ParameterLists:
|
154
|
+
Description: Avoid parameter lists longer than three or four parameters.
|
155
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#too-many-params
|
156
|
+
Enabled: false
|
157
|
+
Max: 5
|
158
|
+
CountKeywordArgs: true
|
159
|
+
Metrics/PerceivedComplexity:
|
160
|
+
Description: A complexity metric geared towards measuring complexity for a human
|
161
|
+
reader.
|
162
|
+
Enabled: false
|
163
|
+
Max: 7
|
164
|
+
Lint/AssignmentInCondition:
|
165
|
+
Description: Don't use assignment in conditions.
|
166
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition
|
167
|
+
Enabled: false
|
168
|
+
AllowSafeAssignment: true
|
169
|
+
Style/InlineComment:
|
170
|
+
Description: Avoid inline comments.
|
171
|
+
Enabled: false
|
172
|
+
Style/AccessorMethodName:
|
173
|
+
Description: Check the naming of accessor methods for get_/set_.
|
174
|
+
Enabled: false
|
175
|
+
Style/Alias:
|
176
|
+
Description: Use alias_method instead of alias.
|
177
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#alias-method
|
178
|
+
Enabled: false
|
179
|
+
Style/Documentation:
|
180
|
+
Description: Document classes and non-namespace modules.
|
181
|
+
Enabled: false
|
182
|
+
Style/ClassVars:
|
183
|
+
Enabled: false
|
184
|
+
Style/DoubleNegation:
|
185
|
+
Description: Checks for uses of double negation (!!).
|
186
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-bang-bang
|
187
|
+
Enabled: false
|
188
|
+
Style/EachWithObject:
|
189
|
+
Description: Prefer `each_with_object` over `inject` or `reduce`.
|
190
|
+
Enabled: false
|
191
|
+
Style/EmptyLiteral:
|
192
|
+
Description: Prefer literals to Array.new/Hash.new/String.new.
|
193
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#literal-array-hash
|
194
|
+
Enabled: false
|
195
|
+
Style/ModuleFunction:
|
196
|
+
Description: Checks for usage of `extend self` in modules.
|
197
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#module-function
|
198
|
+
Enabled: false
|
199
|
+
Style/OneLineConditional:
|
200
|
+
Description: Favor the ternary operator(?:) over if/then/else/end constructs.
|
201
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#ternary-operator
|
202
|
+
Enabled: false
|
203
|
+
Style/PerlBackrefs:
|
204
|
+
Description: Avoid Perl-style regex back references.
|
205
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers
|
206
|
+
Enabled: false
|
207
|
+
Style/Send:
|
208
|
+
Description: Prefer `Object#__send__` or `Object#public_send` to `send`, as `send`
|
209
|
+
may overlap with existing methods.
|
210
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#prefer-public-send
|
211
|
+
Enabled: false
|
212
|
+
Style/GlobalVars:
|
213
|
+
Enabled: false
|
214
|
+
Style/SpecialGlobalVars:
|
215
|
+
Description: Avoid Perl-style global variables.
|
216
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms
|
217
|
+
Enabled: false
|
218
|
+
Style/VariableInterpolation:
|
219
|
+
Description: Don't interpolate global, instance and class variables directly in
|
220
|
+
strings.
|
221
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#curlies-interpolate
|
222
|
+
Enabled: false
|
223
|
+
Style/WhenThen:
|
224
|
+
Description: Use when x then ... for one-line cases.
|
225
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#one-line-cases
|
226
|
+
Enabled: false
|
227
|
+
Lint/EachWithObjectArgument:
|
228
|
+
Description: Check for immutable argument given to each_with_object.
|
229
|
+
Enabled: true
|
230
|
+
Lint/HandleExceptions:
|
231
|
+
Description: Don't suppress exception.
|
232
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions
|
233
|
+
Enabled: false
|
234
|
+
Lint/LiteralInCondition:
|
235
|
+
Description: Checks of literals used in conditions.
|
236
|
+
Enabled: false
|
237
|
+
Lint/LiteralInInterpolation:
|
238
|
+
Description: Checks for literals used in interpolation.
|
239
|
+
Enabled: false
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
@@ -2,8 +2,9 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
gem 'thin', '~> 1.6'
|
4
4
|
|
5
|
-
gem 'pry-byebug', '~> 3.
|
5
|
+
gem 'pry-byebug', '~> 3.3.0', {}.merge(ENV['RM_INFO'] ? { require: false } : {})
|
6
6
|
gem 'rspec', '~> 3.1'
|
7
7
|
gem 'rspec-its', '~> 1.1'
|
8
|
+
gem 'rubocop', '~> 0.35.1'
|
8
9
|
|
9
10
|
gemspec
|
data/README.md
CHANGED
@@ -12,8 +12,8 @@ An HTTP framework for micro-services based environment, build on top of [typhoeu
|
|
12
12
|
|
13
13
|
* Clean restful api supporting http verbs (GET/PUT/POST/DELETE)
|
14
14
|
* Manage Failures - set stubs for case of errors and SERVICE_DOWN event from [Jynx](https://github.com/AvnerCohen/service-jynx)
|
15
|
-
*
|
16
|
-
* Build using Typheous, a fast and
|
15
|
+
* Structured and configurable YAML for multiple service end points
|
16
|
+
* Build using Typheous, a fast and robust http client, built on top of libcurl
|
17
17
|
* Configurable timeouts for http request
|
18
18
|
|
19
19
|
## Configuration
|
@@ -38,14 +38,14 @@ production: &production
|
|
38
38
|
|
39
39
|
</pre>
|
40
40
|
|
41
|
-
###
|
41
|
+
### Configuration Flags
|
42
42
|
|
43
|
-
* use_jynx - Remove the integrated jynx-service protection (default: false)
|
44
|
-
* report_method - proc to be executed in the case of error
|
45
|
-
* env_name - environment name (production|staging|development etc..)
|
46
|
-
* config_folder - path to the configuration folder of the restful_services.yml file.
|
47
|
-
* user_agent -
|
48
|
-
* legacy_postfix - Legacy version accessed the restful_services.yml with an additional postfix in the yaml.
|
43
|
+
* :use_jynx - Remove the integrated jynx-service protection (default: false)
|
44
|
+
* :report_method - proc to be executed in the case of error
|
45
|
+
* :env_name - environment name (production|staging|development etc..)
|
46
|
+
* :config_folder - path to the configuration folder of the restful_services.yml file.
|
47
|
+
* :user_agent - HTTP User-Agent agent, to be added to identify caller (users|mobile_service|anyname etc..)
|
48
|
+
* :legacy_postfix - Legacy version accessed the restful_services.yml with an additional postfix in the yaml.
|
49
49
|
|
50
50
|
## Usage
|
51
51
|
|
@@ -123,7 +123,7 @@ Given:
|
|
123
123
|
````
|
124
124
|
<pre>
|
125
125
|
|
126
|
-
RestfulClient.srv_url('
|
126
|
+
RestfulClient.srv_url('users') # ==> http://1.2.3.4:8383/api/v0/
|
127
127
|
</pre>
|
128
128
|
|
129
129
|
## Contributing
|
data/lib/restful_client.rb
CHANGED
@@ -11,11 +11,15 @@ module RestfulClient
|
|
11
11
|
|
12
12
|
class RestError < StandardError; end
|
13
13
|
|
14
|
-
|
14
|
+
class << self
|
15
|
+
attr_writer :configuration, :logger, :timeout_occured_count
|
16
|
+
end
|
17
|
+
@@configuration = nil
|
15
18
|
@@logger = nil
|
16
19
|
@@timeout_occured_count = 0
|
17
20
|
|
18
21
|
SERVER_SIDE_ERRORS_RANGE = 500
|
22
|
+
CLIENT_SIDE_ERRORS_RANGE = 400
|
19
23
|
|
20
24
|
def self.configure
|
21
25
|
@@configuration ||= RestfulClientConfiguration.new
|
@@ -33,52 +37,54 @@ module RestfulClient
|
|
33
37
|
end
|
34
38
|
|
35
39
|
def srv_url(caller)
|
36
|
-
callerr_config(caller)[
|
40
|
+
callerr_config(caller)['url']
|
37
41
|
end
|
38
42
|
|
39
|
-
def get(caller, path, params = {},
|
40
|
-
url = RestfulClientUri.uri_join(callerr_config(caller)[
|
41
|
-
headers = {
|
42
|
-
headers.merge!(
|
43
|
-
|
43
|
+
def get(caller, path, params = {}, extra = {}, &on_error_block)
|
44
|
+
url = RestfulClientUri.uri_join(callerr_config(caller)['url'], path)
|
45
|
+
headers = { 'Accept' => 'application/json' }
|
46
|
+
headers.merge!(extra.fetch('headers', {}))
|
47
|
+
request_args = { headers: headers, method: 'GET', timeout: timeout, params: params }.merge(extra.fetch('args', {}))
|
48
|
+
request = Typhoeus::Request.new(url, request_args.merge(extra.fetch('args', {})))
|
44
49
|
run_safe_request(caller, request, true, &on_error_block)
|
45
50
|
end
|
46
51
|
|
47
|
-
def post(caller, path, payload,
|
48
|
-
url = RestfulClientUri.uri_join(callerr_config(caller)[
|
49
|
-
headers, payload_as_str = prepare_payload_with_headers(payload,
|
50
|
-
|
52
|
+
def post(caller, path, payload, extra = {}, &on_error_block)
|
53
|
+
url = RestfulClientUri.uri_join(callerr_config(caller)['url'], path)
|
54
|
+
headers, payload_as_str = prepare_payload_with_headers(payload, extra.fetch('headers', {}))
|
55
|
+
request_args = { headers: headers, method: 'POST', body: payload_as_str, timeout: timeout }
|
56
|
+
request = Typhoeus::Request.new(url, request_args.merge(extra.fetch('args', {})))
|
51
57
|
run_safe_request(caller, request, false, &on_error_block)
|
52
58
|
end
|
53
59
|
|
54
60
|
def post_raw(caller, path, payload, custom_timeout = timeout, &on_error_block)
|
55
|
-
url = RestfulClientUri.uri_join(callerr_config(caller)[
|
61
|
+
url = RestfulClientUri.uri_join(callerr_config(caller)['url'], path)
|
56
62
|
request = Typhoeus::Request.new(url, method: 'POST', body: payload, timeout: custom_timeout)
|
57
63
|
run_safe_request(caller, request, false, &on_error_block)
|
58
64
|
end
|
59
65
|
|
60
|
-
def delete(caller, path, payload = {},
|
61
|
-
url = RestfulClientUri.uri_join(callerr_config(caller)[
|
62
|
-
headers, payload_as_str = prepare_payload_with_headers(payload,
|
63
|
-
|
66
|
+
def delete(caller, path, payload = {}, extra = {}, &on_error_block)
|
67
|
+
url = RestfulClientUri.uri_join(callerr_config(caller)['url'], path)
|
68
|
+
headers, payload_as_str = prepare_payload_with_headers(payload, extra.fetch('headers', {}))
|
69
|
+
request_args = { headers: headers, method: 'DELETE', body: payload_as_str, timeout: timeout }
|
70
|
+
request = Typhoeus::Request.new(url, request_args.merge(extra.fetch('args', {})))
|
64
71
|
run_safe_request(caller, request, true, &on_error_block)
|
65
72
|
end
|
66
73
|
|
67
|
-
def put(caller, path, payload,
|
68
|
-
url = RestfulClientUri.uri_join(callerr_config(caller)[
|
69
|
-
headers, payload_as_str = prepare_payload_with_headers(payload,
|
74
|
+
def put(caller, path, payload, extra = {}, &on_error_block)
|
75
|
+
url = RestfulClientUri.uri_join(callerr_config(caller)['url'], path)
|
76
|
+
headers, payload_as_str = prepare_payload_with_headers(payload, extra.fetch('headers', {}))
|
70
77
|
request = Typhoeus::Request.new(url, headers: headers, method: 'PUT', body: payload_as_str, timeout: timeout)
|
71
78
|
run_safe_request(caller, request, false, &on_error_block)
|
72
79
|
end
|
73
80
|
|
74
81
|
def callerr_config(caller)
|
75
82
|
caller_setup = configuration.data["#{caller}#{legacy_postfix}"]
|
76
|
-
|
83
|
+
fail "Couldn't find ['#{caller}#{legacy_postfix}'] in the configuration YAML !!" unless caller_setup
|
77
84
|
caller_setup
|
78
85
|
end
|
79
86
|
|
80
87
|
def run_safe_request(caller, request, retry_if_needed, &on_error_block)
|
81
|
-
|
82
88
|
@@timeout_occured_count = 0
|
83
89
|
if !use_jynx?
|
84
90
|
response = run_request(request.dup, __method__, false)
|
@@ -94,39 +100,43 @@ module RestfulClient
|
|
94
100
|
response
|
95
101
|
rescue => e
|
96
102
|
res = ServiceJynx.failure!(caller) if use_jynx?
|
97
|
-
|
103
|
+
|
104
|
+
if res == :WENT_DOWN
|
105
|
+
report_method.call('ServiceJynx', "Service #{caller} was taken down as a result of exception", e)
|
106
|
+
end
|
107
|
+
|
98
108
|
on_error_block.call("Exception in #{caller} execution - #{e.message}") if on_error_block
|
99
109
|
end
|
100
110
|
|
101
111
|
def run_request(request, method, retry_if_needed)
|
102
112
|
logger.debug { "#{__method__} :: Request :: #{request.inspect}" }
|
103
|
-
request.options[:headers].merge!(
|
104
|
-
request.options[:headers].merge!(
|
113
|
+
request.options[:headers].merge!('X-Forwarded-For' => $client_ip) if $client_ip
|
114
|
+
request.options[:headers].merge!('User-Agent' => user_agent)
|
105
115
|
request.on_complete do |response|
|
106
|
-
#200, OK
|
116
|
+
# 200, OK
|
107
117
|
if response.success?
|
108
118
|
logger.debug { "Success in #{method} :: Code: #{response.response_code}, #{response.body}" }
|
109
|
-
return
|
119
|
+
return '' if response.body.empty?
|
110
120
|
begin
|
111
121
|
return JSON.parse(response.body)
|
112
122
|
rescue => e
|
113
|
-
logger.error { "Response from #{response.effective_url} is not a valid json - [#{response.body}]"}
|
123
|
+
logger.error { "Response from #{response.effective_url} is not a valid json - [#{response.body}]" }
|
114
124
|
raise e
|
115
125
|
end
|
116
|
-
#Timeout occured
|
126
|
+
# Timeout occured
|
117
127
|
elsif response.timed_out?
|
118
|
-
@@timeout_occured_count
|
128
|
+
@@timeout_occured_count += 1
|
119
129
|
skip_raise = (retry_if_needed && @@timeout_occured_count <= retries)
|
120
130
|
|
121
|
-
error_type =
|
131
|
+
error_type = 'TimeoutOccured'
|
122
132
|
error_description = prettify_logger(error_type, request, response)
|
123
133
|
logger.error { "Time out in #{method} for: #{error_description}" }
|
124
134
|
|
125
135
|
exception = RuntimeError.new(error_description)
|
126
136
|
exception.set_backtrace(caller)
|
127
|
-
report_method.call(
|
137
|
+
report_method.call('RestError', error_description, exception)
|
128
138
|
|
129
|
-
|
139
|
+
fail RestError.new(response.return_code.to_sym) unless skip_raise
|
130
140
|
# Could not get an http response, something's wrong.
|
131
141
|
elsif response.code == 0
|
132
142
|
|
@@ -136,8 +146,8 @@ module RestfulClient
|
|
136
146
|
|
137
147
|
exception = RuntimeError.new(error_description)
|
138
148
|
exception.set_backtrace(caller)
|
139
|
-
report_method.call(
|
140
|
-
|
149
|
+
report_method.call('RestError', error_description, exception)
|
150
|
+
fail RestError.new(error_type)
|
141
151
|
# Received a non-successful http response.
|
142
152
|
elsif response.code >= SERVER_SIDE_ERRORS_RANGE
|
143
153
|
|
@@ -145,16 +155,17 @@ module RestfulClient
|
|
145
155
|
error_description = prettify_logger(error_type, request, response)
|
146
156
|
logger.error { "#{error_type} #{response.code}/#{response.return_code} for: #{error_description}" }
|
147
157
|
|
148
|
-
report_method.call("RestError", error_description, exception)
|
149
158
|
exception = RuntimeError.new(error_description)
|
150
|
-
|
151
159
|
exception.set_backtrace(caller)
|
160
|
+
report_method.call('RestError', error_description, exception)
|
152
161
|
|
153
|
-
|
162
|
+
fail RestError.new(error_type)
|
163
|
+
elsif response.code.between?(CLIENT_SIDE_ERRORS_RANGE, (SERVER_SIDE_ERRORS_RANGE - 1))
|
164
|
+
logger.error { "#{error_type} #{response.code}/#{response.return_code} for: #{error_description}" }
|
165
|
+
return ''
|
154
166
|
else
|
155
167
|
|
156
|
-
|
157
|
-
|
168
|
+
fail RestError.new(:BadReturnCode)
|
158
169
|
end
|
159
170
|
end
|
160
171
|
request.run
|
@@ -162,9 +173,9 @@ module RestfulClient
|
|
162
173
|
|
163
174
|
def prepare_payload_with_headers(payload, custom_headers)
|
164
175
|
headers = {}
|
165
|
-
if payload.is_a?(Hash)
|
176
|
+
if payload.is_a?(Hash) && payload.any?
|
166
177
|
payload_as_str = payload.to_json(root: false)
|
167
|
-
headers.merge!(
|
178
|
+
headers.merge!('Content-Type' => 'application/json')
|
168
179
|
else
|
169
180
|
payload_as_str = payload
|
170
181
|
end
|
@@ -174,9 +185,9 @@ module RestfulClient
|
|
174
185
|
[headers, payload_as_str]
|
175
186
|
end
|
176
187
|
|
177
|
-
def fake(caller, path,
|
178
|
-
url = RestfulClientUri.uri_join(callerr_config(caller)[
|
179
|
-
Typhoeus.stub(url,
|
188
|
+
def fake(caller, path, _options = {}, &block)
|
189
|
+
url = RestfulClientUri.uri_join(callerr_config(caller)['url'], path)
|
190
|
+
Typhoeus.stub(url, {}, &block)
|
180
191
|
end
|
181
192
|
|
182
193
|
def timeout
|
@@ -205,7 +216,7 @@ module RestfulClient
|
|
205
216
|
|
206
217
|
def prettify_logger(type, request, response)
|
207
218
|
return "#{type} with no request or response." unless request || response
|
208
|
-
"#{type} #{response.code}/#{response.return_code} for: #{request.options.fetch(:method)}
|
219
|
+
"#{type} #{response.code}/#{response.return_code} for: #{request.options.fetch(:method)}, "\
|
220
|
+
"#{request.base_url}, Total time: #{response.total_time} seconds"
|
209
221
|
end
|
210
|
-
|
211
222
|
end
|
@@ -7,31 +7,30 @@ class RestfulClientConfiguration
|
|
7
7
|
DEFAULT_USER_AGENT = 'RestfulClient - https://github.com/AvnerCohen/restful-client'
|
8
8
|
|
9
9
|
def run!
|
10
|
-
|
11
|
-
file_name = [
|
10
|
+
fail 'Configuration directory name must be provided' unless config_folder.class.to_s == 'String'
|
11
|
+
file_name = ['restful_services.yml', 'rest_api.yml'].each do |name|
|
12
12
|
locale_name = File.join(config_folder, name)
|
13
13
|
break locale_name if File.file?(locale_name)
|
14
14
|
end
|
15
15
|
|
16
16
|
## Set Default Values
|
17
|
-
@report_method
|
18
|
-
@timeout
|
19
|
-
@user_agent
|
20
|
-
@retries
|
21
|
-
@legacy_postfix ||=
|
22
|
-
@use_jynx =
|
17
|
+
@report_method ||= proc { |*_args| nil }
|
18
|
+
@timeout ||= DEFAULT_TIMEOUT
|
19
|
+
@user_agent ||= DEFAULT_USER_AGENT
|
20
|
+
@retries ||= DEFAULT_RETRIES
|
21
|
+
@legacy_postfix ||= ''
|
22
|
+
@use_jynx = true if @use_jynx.nil?
|
23
23
|
|
24
24
|
@data = YAML.load(ERB.new(File.read(file_name)).result)[env].each do |name, entry|
|
25
|
-
next unless entry.
|
25
|
+
next unless entry.key?('url')
|
26
26
|
opts = {
|
27
27
|
time_window_in_seconds: entry.fetch(:time_window_in_seconds, 20),
|
28
28
|
max_errors: entry.fetch(:max_errors, 10),
|
29
29
|
grace_period: entry.fetch(:grace_period, 120)
|
30
30
|
}
|
31
31
|
|
32
|
-
ServiceJynx.register!(name.gsub(@legacy_postfix,
|
32
|
+
ServiceJynx.register!(name.gsub(@legacy_postfix, ''), opts) if @use_jynx
|
33
33
|
end
|
34
|
-
|
35
34
|
end
|
36
35
|
|
37
36
|
def reset
|
@@ -45,11 +44,10 @@ class RestfulClientConfiguration
|
|
45
44
|
|
46
45
|
## Dummy method to test reporting phase
|
47
46
|
def report_on
|
48
|
-
@report_method.call(
|
47
|
+
@report_method.call('RestfulClientConfiguration', "Initialized at: #{Time.now.utc}.")
|
49
48
|
end
|
50
49
|
|
51
50
|
def env
|
52
|
-
@env_name ||
|
51
|
+
@env_name || 'default'
|
53
52
|
end
|
54
|
-
|
55
53
|
end
|
@@ -7,17 +7,18 @@ module RestfulClientLogger
|
|
7
7
|
|
8
8
|
def rails_logger
|
9
9
|
(defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger) ||
|
10
|
-
|
10
|
+
(defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:debug) && RAILS_DEFAULT_LOGGER)
|
11
11
|
end
|
12
12
|
|
13
13
|
def default_logger
|
14
14
|
require 'logger'
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
alogger = Logger.new(STDOUT)
|
16
|
+
alogger.level = Logger::INFO
|
17
|
+
alogger.datetime_format = '%c'
|
18
|
+
alogger
|
18
19
|
end
|
19
20
|
|
20
21
|
def logger=(logger)
|
21
22
|
@logger = logger
|
22
23
|
end
|
23
|
-
end
|
24
|
+
end
|
data/lib/restful_client_uri.rb
CHANGED
data/restful_client.gemspec
CHANGED
@@ -1,26 +1,23 @@
|
|
1
1
|
lib = File.expand_path('../lib', __FILE__)
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require 'restful_client/version'
|
4
3
|
|
5
4
|
Gem::Specification.new do |spec|
|
6
5
|
spec.name = 'restful_client'
|
7
|
-
spec.version =
|
6
|
+
spec.version = '0.3.0'
|
8
7
|
spec.authors = ['Avner Cohen']
|
9
8
|
spec.email = ['israbirding@gmail.com']
|
10
|
-
spec.description =
|
11
|
-
spec.summary =
|
9
|
+
spec.description = 'An HTTP framework for micro-services based environment, build on top of Typheous and Service Jynx'
|
10
|
+
spec.summary = 'An HTTP framework for micro-services based environment'
|
12
11
|
spec.homepage = 'https://github.com/AvnerCohen/restful_client'
|
13
12
|
spec.license = 'MIT'
|
14
13
|
|
15
|
-
spec.files = `git ls-files`.split(
|
14
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
16
15
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
16
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
17
|
spec.require_paths = ['lib']
|
19
18
|
|
20
19
|
spec.add_development_dependency 'bundler'
|
21
|
-
spec.add_development_dependency 'rake'
|
22
20
|
|
23
21
|
spec.add_runtime_dependency 'service_jynx'
|
24
22
|
spec.add_runtime_dependency 'typhoeus'
|
25
23
|
end
|
26
|
-
|