restful_resource 2.8.0 → 2.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +1 -1
- data/.rubocop_todo.yml +119 -70
- data/CHANGELOG.md +20 -0
- data/Gemfile +0 -2
- data/Gemfile.lock +74 -64
- data/lib/restful_resource.rb +2 -1
- data/lib/restful_resource/base.rb +20 -24
- data/lib/restful_resource/http_client.rb +5 -0
- data/lib/restful_resource/open_object.rb +1 -1
- data/lib/restful_resource/rails_validations.rb +4 -1
- data/lib/restful_resource/redirections.rb +6 -4
- data/lib/restful_resource/strict_open_struct.rb +5 -0
- data/lib/restful_resource/version.rb +1 -1
- data/restful_resource.gemspec +9 -8
- data/spec/restful_resource/associations_spec.rb +0 -2
- data/spec/restful_resource/base_spec.rb +14 -14
- data/spec/restful_resource/http_client_configuration_spec.rb +8 -8
- data/spec/restful_resource/http_client_spec.rb +61 -147
- data/spec/restful_resource/rails_validations_spec.rb +59 -10
- data/spec/spec_helper.rb +8 -0
- metadata +48 -33
data/lib/restful_resource.rb
CHANGED
@@ -8,12 +8,13 @@ require 'faraday_cdn_metrics'
|
|
8
8
|
require 'faraday/encoding'
|
9
9
|
require 'active_support'
|
10
10
|
require 'active_support/all'
|
11
|
-
require 'resolv-replace
|
11
|
+
require 'resolv-replace'
|
12
12
|
require_relative 'restful_resource/version'
|
13
13
|
require_relative 'restful_resource/null_logger'
|
14
14
|
require_relative 'restful_resource/paginated_array'
|
15
15
|
require_relative 'restful_resource/parameter_missing_error'
|
16
16
|
require_relative 'restful_resource/resource_id_missing_error'
|
17
|
+
require_relative 'restful_resource/strict_open_struct'
|
17
18
|
require_relative 'restful_resource/open_object'
|
18
19
|
require_relative 'restful_resource/response'
|
19
20
|
require_relative 'restful_resource/request'
|
@@ -34,58 +34,58 @@ module RestfulResource
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def self.find(id, **params)
|
37
|
-
params_without_options, options = format_params(params)
|
37
|
+
params_without_options, options = format_params(**params)
|
38
38
|
|
39
|
-
response = http.get(member_url(id, params_without_options), **options)
|
39
|
+
response = http.get(member_url(id, **params_without_options), **options)
|
40
40
|
new(parse_json(response.body))
|
41
41
|
end
|
42
42
|
|
43
43
|
def self.where(**params)
|
44
|
-
params_without_options, options = format_params(params)
|
44
|
+
params_without_options, options = format_params(**params)
|
45
45
|
|
46
|
-
url = collection_url(params_without_options)
|
46
|
+
url = collection_url(**params_without_options)
|
47
47
|
response = http.get(url, **options)
|
48
48
|
paginate_response(response)
|
49
49
|
end
|
50
50
|
|
51
51
|
def self.get(**params)
|
52
|
-
params_without_options, options = format_params(params)
|
52
|
+
params_without_options, options = format_params(**params)
|
53
53
|
|
54
|
-
response = http.get(collection_url(params_without_options), **options)
|
54
|
+
response = http.get(collection_url(**params_without_options), **options)
|
55
55
|
new(parse_json(response.body))
|
56
56
|
end
|
57
57
|
|
58
58
|
def self.delete(id, **params)
|
59
|
-
params_without_options, options = format_params(params)
|
60
|
-
response = http.delete(member_url(id, params_without_options), **options)
|
61
|
-
|
59
|
+
params_without_options, options = format_params(**params)
|
60
|
+
response = http.delete(member_url(id, **params_without_options), **options)
|
61
|
+
new(parse_json(response.body))
|
62
62
|
end
|
63
63
|
|
64
64
|
def self.patch(id, data: {}, headers: {}, **params)
|
65
|
-
params_without_options, options = format_params(params)
|
65
|
+
params_without_options, options = format_params(**params)
|
66
66
|
options.delete(:headers)
|
67
67
|
|
68
|
-
url = member_url(id, params_without_options)
|
68
|
+
url = member_url(id, **params_without_options)
|
69
69
|
|
70
70
|
response = http.patch(url, data: data, headers: headers, **options)
|
71
71
|
new(parse_json(response.body))
|
72
72
|
end
|
73
73
|
|
74
74
|
def self.put(id, data: {}, headers: {}, **params)
|
75
|
-
params_without_options, options = format_params(params)
|
75
|
+
params_without_options, options = format_params(**params)
|
76
76
|
options.delete(:headers)
|
77
77
|
|
78
|
-
url = member_url(id, params_without_options)
|
78
|
+
url = member_url(id, **params_without_options)
|
79
79
|
|
80
80
|
response = http.put(url, data: data, headers: headers, **options)
|
81
81
|
new(parse_json(response.body))
|
82
82
|
end
|
83
83
|
|
84
84
|
def self.post(data: {}, headers: {}, **params)
|
85
|
-
params_without_options, options = format_params(params)
|
85
|
+
params_without_options, options = format_params(**params)
|
86
86
|
options.delete(:headers)
|
87
87
|
|
88
|
-
url = collection_url(params_without_options)
|
88
|
+
url = collection_url(**params_without_options)
|
89
89
|
|
90
90
|
response = http.post(url, data: data, headers: headers, **options)
|
91
91
|
|
@@ -93,7 +93,7 @@ module RestfulResource
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def self.all(**params)
|
96
|
-
where(params)
|
96
|
+
where(**params)
|
97
97
|
end
|
98
98
|
|
99
99
|
def self.action(action_name)
|
@@ -119,8 +119,6 @@ module RestfulResource
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
-
protected
|
123
|
-
|
124
122
|
def self.http
|
125
123
|
@http || superclass.http
|
126
124
|
end
|
@@ -135,11 +133,9 @@ module RestfulResource
|
|
135
133
|
|
136
134
|
def self.collection_url(**params)
|
137
135
|
url = merge_url_paths(base_url, @resource_path, @action_prefix)
|
138
|
-
replace_parameters(url, params)
|
136
|
+
replace_parameters(url, **params)
|
139
137
|
end
|
140
138
|
|
141
|
-
private
|
142
|
-
|
143
139
|
def self.format_params(**params)
|
144
140
|
headers = params.delete(:headers) || {}
|
145
141
|
|
@@ -147,7 +143,7 @@ module RestfulResource
|
|
147
143
|
open_timeout = params.delete(:open_timeout)
|
148
144
|
timeout = params.delete(:timeout)
|
149
145
|
|
150
|
-
[params, headers: headers, open_timeout: open_timeout, timeout: timeout]
|
146
|
+
[params, { headers: headers, open_timeout: open_timeout, timeout: timeout }]
|
151
147
|
end
|
152
148
|
|
153
149
|
def self.merge_url_paths(uri, *paths)
|
@@ -158,7 +154,7 @@ module RestfulResource
|
|
158
154
|
raise ResourceIdMissingError if id.blank?
|
159
155
|
|
160
156
|
url = merge_url_paths(base_url, @resource_path, CGI.escape(id.to_s), @action_prefix)
|
161
|
-
replace_parameters(url, params)
|
157
|
+
replace_parameters(url, **params)
|
162
158
|
end
|
163
159
|
|
164
160
|
def self.new_collection(json)
|
@@ -177,7 +173,7 @@ module RestfulResource
|
|
177
173
|
missing_params = []
|
178
174
|
params = params.with_indifferent_access
|
179
175
|
|
180
|
-
url_params = url.scan(
|
176
|
+
url_params = url.scan(%r{:([A-Za-z][^/]*)}).flatten
|
181
177
|
url_params.each do |key|
|
182
178
|
value = params.delete(key)
|
183
179
|
if value.nil?
|
@@ -265,6 +265,11 @@ module RestfulResource
|
|
265
265
|
response = e.response
|
266
266
|
raise ClientError, request unless response
|
267
267
|
|
268
|
+
handle_error(request, response)
|
269
|
+
rescue Faraday::ServerError => e
|
270
|
+
response = e.response
|
271
|
+
raise ClientError, request unless response
|
272
|
+
|
268
273
|
handle_error(request, response)
|
269
274
|
end
|
270
275
|
|
@@ -17,13 +17,16 @@ module RestfulResource
|
|
17
17
|
with_validations { super }
|
18
18
|
end
|
19
19
|
|
20
|
+
def delete(*)
|
21
|
+
with_validations { super }
|
22
|
+
end
|
23
|
+
|
20
24
|
private
|
21
25
|
|
22
26
|
def with_validations(id = nil, data: {})
|
23
27
|
yield
|
24
28
|
rescue HttpClient::UnprocessableEntity => e
|
25
29
|
errors = parse_json(e.response.body)
|
26
|
-
result = nil
|
27
30
|
result = if errors.is_a?(Hash) && errors.key?('errors')
|
28
31
|
data.merge(errors)
|
29
32
|
else
|
@@ -9,15 +9,17 @@ module RestfulResource
|
|
9
9
|
def self.included(base)
|
10
10
|
base.instance_eval do
|
11
11
|
def post(data: {}, delay: 1.0, max_attempts: 10, headers: {}, open_timeout: nil, timeout: nil, **params)
|
12
|
-
url = collection_url(params)
|
12
|
+
url = collection_url(**params)
|
13
13
|
|
14
|
-
response = accept_redirected_result(
|
14
|
+
response = accept_redirected_result(
|
15
|
+
response: http.post(url, data: data, headers: headers, open_timeout: nil, timeout: nil),
|
16
|
+
delay: delay,
|
17
|
+
max_attempts: max_attempts
|
18
|
+
)
|
15
19
|
|
16
20
|
new(parse_json(response.body))
|
17
21
|
end
|
18
22
|
|
19
|
-
private
|
20
|
-
|
21
23
|
def self.accept_redirected_result(response:, delay:, max_attempts:)
|
22
24
|
new_response = response
|
23
25
|
if response.status == 303
|
data/restful_resource.gemspec
CHANGED
@@ -20,18 +20,19 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency 'bundler'
|
22
22
|
spec.add_development_dependency 'carwow_rubocop'
|
23
|
+
spec.add_development_dependency 'pry'
|
23
24
|
spec.add_development_dependency 'rake'
|
24
25
|
spec.add_development_dependency 'rspec'
|
25
|
-
spec.add_development_dependency 'rspec_junit_formatter'
|
26
26
|
spec.add_development_dependency 'rspec-its'
|
27
|
+
spec.add_development_dependency 'rspec_junit_formatter'
|
27
28
|
|
28
|
-
spec.add_dependency 'activesupport'
|
29
|
-
spec.add_dependency 'faraday', '~>
|
30
|
-
spec.add_dependency 'faraday-cdn-metrics'
|
29
|
+
spec.add_dependency 'activesupport', '~> 6.0'
|
30
|
+
spec.add_dependency 'faraday', '~> 1.0'
|
31
|
+
spec.add_dependency 'faraday-cdn-metrics', '~> 0.2'
|
31
32
|
spec.add_dependency 'faraday-encoding'
|
32
|
-
spec.add_dependency 'faraday-http-cache'
|
33
|
-
spec.add_dependency 'faraday_middleware'
|
33
|
+
spec.add_dependency 'faraday-http-cache', '~> 2.2'
|
34
|
+
spec.add_dependency 'faraday_middleware', '~> 1.0'
|
34
35
|
spec.add_dependency 'link_header'
|
35
|
-
spec.add_dependency 'rack'
|
36
|
-
spec.add_dependency 'typhoeus'
|
36
|
+
spec.add_dependency 'rack', '~> 2.2'
|
37
|
+
spec.add_dependency 'typhoeus', '~> 1.4'
|
37
38
|
end
|
@@ -11,7 +11,6 @@ describe RestfulResource::Associations do
|
|
11
11
|
{ first_name: 'David', second_name: 'Doe' },
|
12
12
|
{ first_name: 'Mary', second_name: 'Doe' }
|
13
13
|
]
|
14
|
-
|
15
14
|
)
|
16
15
|
end
|
17
16
|
|
@@ -39,7 +38,6 @@ describe RestfulResource::Associations do
|
|
39
38
|
@child = ComplicatedModule::Child.new(
|
40
39
|
first_name: 'David', second_name: 'Smith',
|
41
40
|
parent: { name: 'John Smith' }
|
42
|
-
|
43
41
|
)
|
44
42
|
end
|
45
43
|
|
@@ -365,17 +365,17 @@ RSpec.describe RestfulResource::Base do
|
|
365
365
|
end
|
366
366
|
|
367
367
|
it 'does not return inner object table' do
|
368
|
-
expect(@makes.first.as_json).to eq
|
368
|
+
expect(@makes.first.as_json).to eq({ 'name' => 'Audi', 'slug' => 'Audi-Slug' })
|
369
369
|
end
|
370
370
|
|
371
371
|
it 'returns inner object table on selected fields' do
|
372
|
-
expect(@makes.last.as_json(only: [:name])).to eq
|
372
|
+
expect(@makes.last.as_json(only: [:name])).to eq({ 'name' => 'Fiat' })
|
373
373
|
end
|
374
374
|
end
|
375
375
|
|
376
376
|
describe '.member_url' do
|
377
377
|
it 'requires a member ID' do
|
378
|
-
expect { described_class.member_url(''
|
378
|
+
expect { described_class.member_url('') }.to raise_error(RestfulResource::ResourceIdMissingError)
|
379
379
|
end
|
380
380
|
end
|
381
381
|
|
@@ -406,17 +406,17 @@ RSpec.describe RestfulResource::Base do
|
|
406
406
|
)
|
407
407
|
|
408
408
|
client.configure(base_url: 'http://foo.bar',
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
409
|
+
username: username,
|
410
|
+
password: password,
|
411
|
+
auth_token: auth_token,
|
412
|
+
logger: logger,
|
413
|
+
cache_store: cache_store,
|
414
|
+
instrumentation: instrumentation,
|
415
|
+
timeout: timeout,
|
416
|
+
open_timeout: open_timeout,
|
417
|
+
faraday_config: faraday_config,
|
418
|
+
faraday_options: faraday_options
|
419
|
+
)
|
420
420
|
end
|
421
421
|
end
|
422
422
|
|
@@ -19,7 +19,7 @@ describe RestfulResource::HttpClient do
|
|
19
19
|
|
20
20
|
describe 'Builder configuration' do
|
21
21
|
it 'uses the typhoeus adapter' do
|
22
|
-
expect(
|
22
|
+
expect(connection.adapter).to eq Faraday::Adapter::Typhoeus
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'url_encodes requests' do
|
@@ -81,13 +81,13 @@ describe RestfulResource::HttpClient do
|
|
81
81
|
described_class.new(instrumentation: { app_name: 'rails', api_name: 'api', metric_class: FakeMetrics })
|
82
82
|
|
83
83
|
expect(RestfulResource::Instrumentation).to have_received(:new)
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
84
|
+
.with(app_name: 'rails',
|
85
|
+
api_name: 'api',
|
86
|
+
request_instrument_name: 'http.api',
|
87
|
+
cache_instrument_name: 'http_cache.api',
|
88
|
+
server_cache_instrument_name: 'cdn_metrics.api',
|
89
|
+
metric_class: FakeMetrics
|
90
|
+
)
|
91
91
|
end
|
92
92
|
|
93
93
|
it 'subscribes to the notifications' do
|
@@ -16,175 +16,97 @@ RSpec.describe RestfulResource::HttpClient do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
describe 'Basic HTTP' do
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
response = http_client(connection).get('http://httpbin.org/get')
|
25
|
-
expect(response.status).to eq 200
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'executes patch' do
|
29
|
-
connection = faraday_connection do |stubs|
|
30
|
-
# Note: request body is serialized as url-encoded so the stub body must be in the same format to match
|
31
|
-
stubs.patch('http://httpbin.org/patch', 'name=Alfred') { |_env| [200, {}, nil] }
|
32
|
-
end
|
33
|
-
|
34
|
-
response = http_client(connection).patch('http://httpbin.org/patch', data: { name: 'Alfred' })
|
35
|
-
expect(response.status).to eq 200
|
36
|
-
end
|
19
|
+
shared_examples 'error codes throw exception' do |verb, status, exception_class|
|
20
|
+
it "raises an error #{status}" do
|
21
|
+
url = "http://httpbin.org/status/#{status}"
|
37
22
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
stubs.put('http://httpbin.org/put', 'name=Alfred') { |_env| [200, {}, nil] }
|
42
|
-
end
|
43
|
-
|
44
|
-
response = http_client(connection).put('http://httpbin.org/put', data: { name: 'Alfred' })
|
45
|
-
expect(response.status).to eq 200
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'executes post' do
|
49
|
-
connection = faraday_connection do |stubs|
|
50
|
-
# Note: request body is serialized as url-encoded so the stub body must be in the same format to match
|
51
|
-
stubs.post('http://httpbin.org/post', 'name=Alfred') { |_env| [200, {}, %("name": "Alfred")] }
|
52
|
-
end
|
53
|
-
|
54
|
-
response = http_client(connection).post('http://httpbin.org/post', data: { name: 'Alfred' })
|
55
|
-
|
56
|
-
expect(response.body).to include 'name": "Alfred'
|
57
|
-
expect(response.status).to eq 200
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'executes delete' do
|
61
|
-
connection = faraday_connection do |stubs|
|
62
|
-
stubs.delete('http://httpbin.org/delete') { |_env| [200, {}, nil] }
|
63
|
-
end
|
64
|
-
|
65
|
-
response = http_client(connection).delete('http://httpbin.org/delete')
|
66
|
-
|
67
|
-
expect(response.status).to eq 200
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'patch should raise error 409' do
|
71
|
-
connection = faraday_connection do |stubs|
|
72
|
-
stubs.patch('http://httpbin.org/status/409') { |_env| [409, {}, nil] }
|
73
|
-
end
|
74
|
-
|
75
|
-
expect { http_client(connection).patch('http://httpbin.org/status/409') }.to raise_error(RestfulResource::HttpClient::Conflict)
|
76
|
-
end
|
23
|
+
connection = faraday_connection do |stubs|
|
24
|
+
stubs.send(verb, url) { [status, {}, nil] }
|
25
|
+
end
|
77
26
|
|
78
|
-
|
79
|
-
connection = faraday_connection do |stubs|
|
80
|
-
stubs.patch('http://httpbin.org/status/422') { |_env| [422, {}, nil] }
|
27
|
+
expect { http_client(connection).send(verb, url) }.to raise_error(exception_class)
|
81
28
|
end
|
82
|
-
|
83
|
-
expect { http_client(connection).patch('http://httpbin.org/status/422') }.to raise_error(RestfulResource::HttpClient::UnprocessableEntity)
|
84
29
|
end
|
85
30
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
31
|
+
shared_examples 'raise an exception on error responses' do |verb|
|
32
|
+
include_examples 'error codes throw exception', verb, 409, RestfulResource::HttpClient::Conflict
|
33
|
+
include_examples 'error codes throw exception', verb, 404, RestfulResource::HttpClient::ResourceNotFound
|
34
|
+
include_examples 'error codes throw exception', verb, 422, RestfulResource::HttpClient::UnprocessableEntity
|
35
|
+
include_examples 'error codes throw exception', verb, 429, RestfulResource::HttpClient::TooManyRequests
|
36
|
+
include_examples 'error codes throw exception', verb, 502, RestfulResource::HttpClient::BadGateway
|
37
|
+
include_examples 'error codes throw exception', verb, 503, RestfulResource::HttpClient::ServiceUnavailable
|
38
|
+
include_examples 'error codes throw exception', verb, 504, RestfulResource::HttpClient::GatewayTimeout
|
90
39
|
|
91
|
-
|
40
|
+
include_examples 'error codes throw exception', verb, 418, RestfulResource::HttpClient::OtherHttpError
|
92
41
|
end
|
93
42
|
|
94
|
-
|
95
|
-
|
96
|
-
stubs.put('http://httpbin.org/status/422') { |_env| [422, {}, nil] }
|
97
|
-
end
|
43
|
+
context 'GET' do
|
44
|
+
include_examples 'raise an exception on error responses', :get
|
98
45
|
|
99
|
-
|
100
|
-
|
46
|
+
it 'executes get' do
|
47
|
+
connection = faraday_connection do |stubs|
|
48
|
+
stubs.get('http://httpbin.org/get') { |_env| [200, {}, nil] }
|
49
|
+
end
|
101
50
|
|
102
|
-
|
103
|
-
|
104
|
-
stubs.post('http://httpbin.org/status/422') { |_env| [422, {}, nil] }
|
51
|
+
response = http_client(connection).get('http://httpbin.org/get')
|
52
|
+
expect(response.status).to eq 200
|
105
53
|
end
|
106
|
-
|
107
|
-
expect { http_client(connection).post('http://httpbin.org/status/422') }.to raise_error(RestfulResource::HttpClient::UnprocessableEntity)
|
108
54
|
end
|
109
55
|
|
110
|
-
|
111
|
-
|
112
|
-
stubs.post('http://httpbin.org/status/429') { |_env| [429, {}, nil] }
|
113
|
-
end
|
56
|
+
context 'PATCH' do
|
57
|
+
include_examples 'raise an exception on error responses', :patch
|
114
58
|
|
115
|
-
|
116
|
-
|
59
|
+
it 'executes patch' do
|
60
|
+
connection = faraday_connection do |stubs|
|
61
|
+
# NOTE: request body is serialized as url-encoded so the stub body must be in the same format to match
|
62
|
+
stubs.patch('http://httpbin.org/patch', 'name=Alfred') { |_env| [200, {}, nil] }
|
63
|
+
end
|
117
64
|
|
118
|
-
|
119
|
-
|
120
|
-
stubs.patch('http://httpbin.org/status/502') { |_env| [502, {}, nil] }
|
65
|
+
response = http_client(connection).patch('http://httpbin.org/patch', data: { name: 'Alfred' })
|
66
|
+
expect(response.status).to eq 200
|
121
67
|
end
|
122
|
-
|
123
|
-
expect { http_client(connection).patch('http://httpbin.org/status/502') }.to raise_error(RestfulResource::HttpClient::BadGateway)
|
124
68
|
end
|
125
69
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
70
|
+
context 'PUT' do
|
71
|
+
include_examples 'raise an exception on error responses', :put
|
72
|
+
it 'executes put' do
|
73
|
+
connection = faraday_connection do |stubs|
|
74
|
+
# NOTE: request body is serialized as url-encoded so the stub body must be in the same format to match
|
75
|
+
stubs.put('http://httpbin.org/put', 'name=Alfred') { |_env| [200, {}, nil] }
|
76
|
+
end
|
133
77
|
|
134
|
-
|
135
|
-
|
136
|
-
stubs.post('http://httpbin.org/status/502') { |_env| [502, {}, nil] }
|
78
|
+
response = http_client(connection).put('http://httpbin.org/put', data: { name: 'Alfred' })
|
79
|
+
expect(response.status).to eq 200
|
137
80
|
end
|
138
|
-
|
139
|
-
expect { http_client(connection).post('http://httpbin.org/status/502') }.to raise_error(RestfulResource::HttpClient::BadGateway)
|
140
81
|
end
|
141
82
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
83
|
+
context 'POST' do
|
84
|
+
include_examples 'raise an exception on error responses', :post
|
85
|
+
it 'executes post' do
|
86
|
+
connection = faraday_connection do |stubs|
|
87
|
+
# NOTE: request body is serialized as url-encoded so the stub body must be in the same format to match
|
88
|
+
stubs.post('http://httpbin.org/post', 'name=Alfred') { |_env| [200, {}, %("name": "Alfred")] }
|
89
|
+
end
|
146
90
|
|
147
|
-
|
148
|
-
end
|
91
|
+
response = http_client(connection).post('http://httpbin.org/post', data: { name: 'Alfred' })
|
149
92
|
|
150
|
-
|
151
|
-
|
152
|
-
stubs.put('http://httpbin.org/status/503') { |_env| [503, {}, nil] }
|
93
|
+
expect(response.body).to include 'name": "Alfred'
|
94
|
+
expect(response.status).to eq 200
|
153
95
|
end
|
154
|
-
|
155
|
-
expect { http_client(connection).put('http://httpbin.org/status/503') }.to raise_error(RestfulResource::HttpClient::ServiceUnavailable)
|
156
96
|
end
|
157
97
|
|
158
|
-
|
159
|
-
|
160
|
-
stubs.post('http://httpbin.org/status/503') { |_env| [503, {}, nil] }
|
161
|
-
end
|
98
|
+
context 'DELETE' do
|
99
|
+
include_examples 'raise an exception on error responses', :delete
|
162
100
|
|
163
|
-
|
164
|
-
|
101
|
+
it 'executes delete' do
|
102
|
+
connection = faraday_connection do |stubs|
|
103
|
+
stubs.delete('http://httpbin.org/delete') { |_env| [200, {}, nil] }
|
104
|
+
end
|
165
105
|
|
166
|
-
|
167
|
-
connection = faraday_connection do |stubs|
|
168
|
-
stubs.post('http://httpbin.org/status/504') { |_env| [504, {}, nil] }
|
169
|
-
end
|
106
|
+
response = http_client(connection).delete('http://httpbin.org/delete')
|
170
107
|
|
171
|
-
|
172
|
-
end
|
173
|
-
|
174
|
-
it 'raises error on 404' do
|
175
|
-
connection = faraday_connection do |stubs|
|
176
|
-
stubs.get('http://httpbin.org/status/404') { |_env| [404, {}, nil] }
|
177
|
-
stubs.post('http://httpbin.org/status/404') { |_env| [404, {}, nil] }
|
178
|
-
stubs.patch('http://httpbin.org/status/404') { |_env| [404, {}, nil] }
|
179
|
-
stubs.put('http://httpbin.org/status/404') { |_env| [404, {}, nil] }
|
180
|
-
stubs.delete('http://httpbin.org/status/404') { |_env| [404, {}, nil] }
|
108
|
+
expect(response.status).to eq 200
|
181
109
|
end
|
182
|
-
|
183
|
-
expect { http_client(connection).get('http://httpbin.org/status/404') }.to raise_error(RestfulResource::HttpClient::ResourceNotFound)
|
184
|
-
expect { http_client(connection).delete('http://httpbin.org/status/404') }.to raise_error(RestfulResource::HttpClient::ResourceNotFound)
|
185
|
-
expect { http_client(connection).patch('http://httpbin.org/status/404', data: { name: 'Mad cow' }) }.to raise_error(RestfulResource::HttpClient::ResourceNotFound)
|
186
|
-
expect { http_client(connection).put('http://httpbin.org/status/404', data: { name: 'Mad cow' }) }.to raise_error(RestfulResource::HttpClient::ResourceNotFound)
|
187
|
-
expect { http_client(connection).post('http://httpbin.org/status/404', data: { name: 'Mad cow' }) }.to raise_error(RestfulResource::HttpClient::ResourceNotFound)
|
188
110
|
end
|
189
111
|
|
190
112
|
it 'raises Faraday::ConnectionFailed errors' do
|
@@ -210,14 +132,6 @@ RSpec.describe RestfulResource::HttpClient do
|
|
210
132
|
|
211
133
|
expect { http_client(connection).get('https://localhost:3005') }.to raise_error(RestfulResource::HttpClient::ClientError)
|
212
134
|
end
|
213
|
-
|
214
|
-
it 'raises OtherHttpError for other status response codes' do
|
215
|
-
connection = faraday_connection do |stubs|
|
216
|
-
stubs.get('http://httpbin.org/status/418') { |_env| [418, {}, nil] }
|
217
|
-
end
|
218
|
-
|
219
|
-
expect { http_client(connection).get('http://httpbin.org/status/418') }.to raise_error(RestfulResource::HttpClient::OtherHttpError)
|
220
|
-
end
|
221
135
|
end
|
222
136
|
|
223
137
|
describe 'Authentication' do
|
@@ -305,10 +219,10 @@ RSpec.describe RestfulResource::HttpClient do
|
|
305
219
|
conn
|
306
220
|
end
|
307
221
|
|
308
|
-
|
309
222
|
context 'when explicit timeout set on connection' do
|
310
223
|
let(:timeout) { 5 }
|
311
224
|
let(:required_headers) { { 'X-Client-Timeout' => 5 } }
|
225
|
+
|
312
226
|
it 'sets X-Client-Timeout correctly' do
|
313
227
|
response = http_client.get('http://httpbin.org/get')
|
314
228
|
|