dhc 1.0.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 +7 -0
- data/.github/workflows/rubocop.yml +27 -0
- data/.github/workflows/test.yml +27 -0
- data/.gitignore +37 -0
- data/.rubocop.yml +105 -0
- data/.ruby-version +1 -0
- data/Gemfile +5 -0
- data/LICENSE +674 -0
- data/README.md +999 -0
- data/Rakefile +25 -0
- data/dhc.gemspec +40 -0
- data/lib/core_ext/hash/deep_transform_values.rb +48 -0
- data/lib/dhc.rb +77 -0
- data/lib/dhc/concerns/dhc/basic_methods_concern.rb +42 -0
- data/lib/dhc/concerns/dhc/configuration_concern.rb +20 -0
- data/lib/dhc/concerns/dhc/fix_invalid_encoding_concern.rb +42 -0
- data/lib/dhc/concerns/dhc/formats_concern.rb +25 -0
- data/lib/dhc/concerns/dhc/request/user_agent_concern.rb +25 -0
- data/lib/dhc/config.rb +47 -0
- data/lib/dhc/endpoint.rb +119 -0
- data/lib/dhc/error.rb +82 -0
- data/lib/dhc/errors/client_error.rb +73 -0
- data/lib/dhc/errors/parser_error.rb +4 -0
- data/lib/dhc/errors/server_error.rb +28 -0
- data/lib/dhc/errors/timeout.rb +4 -0
- data/lib/dhc/errors/unknown_error.rb +4 -0
- data/lib/dhc/format.rb +18 -0
- data/lib/dhc/formats.rb +8 -0
- data/lib/dhc/formats/form.rb +45 -0
- data/lib/dhc/formats/json.rb +55 -0
- data/lib/dhc/formats/multipart.rb +45 -0
- data/lib/dhc/formats/plain.rb +42 -0
- data/lib/dhc/interceptor.rb +36 -0
- data/lib/dhc/interceptors.rb +26 -0
- data/lib/dhc/interceptors/auth.rb +94 -0
- data/lib/dhc/interceptors/caching.rb +148 -0
- data/lib/dhc/interceptors/default_timeout.rb +16 -0
- data/lib/dhc/interceptors/logging.rb +37 -0
- data/lib/dhc/interceptors/monitoring.rb +92 -0
- data/lib/dhc/interceptors/prometheus.rb +51 -0
- data/lib/dhc/interceptors/retry.rb +41 -0
- data/lib/dhc/interceptors/rollbar.rb +36 -0
- data/lib/dhc/interceptors/throttle.rb +86 -0
- data/lib/dhc/interceptors/zipkin.rb +110 -0
- data/lib/dhc/railtie.rb +9 -0
- data/lib/dhc/request.rb +161 -0
- data/lib/dhc/response.rb +60 -0
- data/lib/dhc/response/data.rb +28 -0
- data/lib/dhc/response/data/base.rb +18 -0
- data/lib/dhc/response/data/collection.rb +16 -0
- data/lib/dhc/response/data/item.rb +29 -0
- data/lib/dhc/rspec.rb +11 -0
- data/lib/dhc/test/cache_helper.rb +3 -0
- data/lib/dhc/version.rb +5 -0
- data/script/ci/build.sh +19 -0
- data/spec/basic_methods/delete_spec.rb +34 -0
- data/spec/basic_methods/get_spec.rb +49 -0
- data/spec/basic_methods/post_spec.rb +42 -0
- data/spec/basic_methods/put_spec.rb +48 -0
- data/spec/basic_methods/request_spec.rb +19 -0
- data/spec/basic_methods/request_without_rails_spec.rb +29 -0
- data/spec/config/endpoints_spec.rb +63 -0
- data/spec/config/placeholders_spec.rb +32 -0
- data/spec/core_ext/hash/deep_transform_values_spec.rb +24 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +8 -0
- data/spec/dummy/app/assets/config/manifest.js +3 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +7 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/helpers/application_helper.rb +4 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +5 -0
- data/spec/dummy/bin/rails +6 -0
- data/spec/dummy/bin/rake +6 -0
- data/spec/dummy/config.ru +6 -0
- data/spec/dummy/config/application.rb +16 -0
- data/spec/dummy/config/boot.rb +7 -0
- data/spec/dummy/config/environment.rb +7 -0
- data/spec/dummy/config/environments/development.rb +36 -0
- data/spec/dummy/config/environments/production.rb +77 -0
- data/spec/dummy/config/environments/test.rb +41 -0
- data/spec/dummy/config/initializers/assets.rb +10 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +6 -0
- data/spec/dummy/config/initializers/inflections.rb +18 -0
- data/spec/dummy/config/initializers/mime_types.rb +6 -0
- data/spec/dummy/config/initializers/session_store.rb +5 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +11 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/endpoint/compile_spec.rb +35 -0
- data/spec/endpoint/match_spec.rb +41 -0
- data/spec/endpoint/placeholders_spec.rb +30 -0
- data/spec/endpoint/remove_interpolated_params_spec.rb +17 -0
- data/spec/endpoint/values_as_params_spec.rb +31 -0
- data/spec/error/dup_spec.rb +12 -0
- data/spec/error/find_spec.rb +57 -0
- data/spec/error/response_spec.rb +17 -0
- data/spec/error/timeout_spec.rb +14 -0
- data/spec/error/to_s_spec.rb +85 -0
- data/spec/formats/form_spec.rb +27 -0
- data/spec/formats/json_spec.rb +66 -0
- data/spec/formats/multipart_spec.rb +26 -0
- data/spec/formats/plain_spec.rb +29 -0
- data/spec/interceptors/after_request_spec.rb +20 -0
- data/spec/interceptors/after_response_spec.rb +39 -0
- data/spec/interceptors/auth/basic_auth_spec.rb +17 -0
- data/spec/interceptors/auth/bearer_spec.rb +19 -0
- data/spec/interceptors/auth/body_spec.rb +36 -0
- data/spec/interceptors/auth/long_basic_auth_credentials_spec.rb +17 -0
- data/spec/interceptors/auth/no_instance_var_for_options_spec.rb +27 -0
- data/spec/interceptors/auth/reauthentication_configuration_spec.rb +61 -0
- data/spec/interceptors/auth/reauthentication_spec.rb +44 -0
- data/spec/interceptors/before_request_spec.rb +21 -0
- data/spec/interceptors/before_response_spec.rb +20 -0
- data/spec/interceptors/caching/hydra_spec.rb +26 -0
- data/spec/interceptors/caching/main_spec.rb +73 -0
- data/spec/interceptors/caching/methods_spec.rb +42 -0
- data/spec/interceptors/caching/multilevel_cache_spec.rb +139 -0
- data/spec/interceptors/caching/options_spec.rb +78 -0
- data/spec/interceptors/caching/parameters_spec.rb +24 -0
- data/spec/interceptors/caching/response_status_spec.rb +29 -0
- data/spec/interceptors/caching/to_cache_spec.rb +16 -0
- data/spec/interceptors/default_interceptors_spec.rb +15 -0
- data/spec/interceptors/default_timeout/main_spec.rb +34 -0
- data/spec/interceptors/define_spec.rb +30 -0
- data/spec/interceptors/dup_spec.rb +19 -0
- data/spec/interceptors/logging/main_spec.rb +37 -0
- data/spec/interceptors/monitoring/caching_spec.rb +66 -0
- data/spec/interceptors/monitoring/main_spec.rb +97 -0
- data/spec/interceptors/prometheus_spec.rb +54 -0
- data/spec/interceptors/response_competition_spec.rb +39 -0
- data/spec/interceptors/retry/main_spec.rb +73 -0
- data/spec/interceptors/return_response_spec.rb +38 -0
- data/spec/interceptors/rollbar/invalid_encoding_spec.rb +43 -0
- data/spec/interceptors/rollbar/main_spec.rb +57 -0
- data/spec/interceptors/throttle/main_spec.rb +236 -0
- data/spec/interceptors/throttle/reset_track_spec.rb +53 -0
- data/spec/interceptors/zipkin/distributed_tracing_spec.rb +135 -0
- data/spec/rails_helper.rb +6 -0
- data/spec/request/body_spec.rb +39 -0
- data/spec/request/encoding_spec.rb +38 -0
- data/spec/request/error_handling_spec.rb +88 -0
- data/spec/request/headers_spec.rb +12 -0
- data/spec/request/ignore_errors_spec.rb +73 -0
- data/spec/request/option_dup_spec.rb +13 -0
- data/spec/request/parallel_requests_spec.rb +59 -0
- data/spec/request/params_encoding_spec.rb +26 -0
- data/spec/request/request_without_rails_spec.rb +15 -0
- data/spec/request/url_patterns_spec.rb +54 -0
- data/spec/request/user_agent_spec.rb +26 -0
- data/spec/request/user_agent_without_rails_spec.rb +27 -0
- data/spec/response/body_spec.rb +16 -0
- data/spec/response/code_spec.rb +16 -0
- data/spec/response/data_accessor_spec.rb +29 -0
- data/spec/response/data_spec.rb +85 -0
- data/spec/response/effective_url_spec.rb +16 -0
- data/spec/response/headers_spec.rb +18 -0
- data/spec/response/options_spec.rb +18 -0
- data/spec/response/success_spec.rb +13 -0
- data/spec/response/time_spec.rb +21 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/support/fixtures/json/feedback.json +11 -0
- data/spec/support/fixtures/json/feedbacks.json +164 -0
- data/spec/support/fixtures/json/localina_content_ad.json +23 -0
- data/spec/support/load_json.rb +5 -0
- data/spec/support/reset_config.rb +8 -0
- data/spec/support/zipkin_mock.rb +114 -0
- data/spec/timeouts/no_signal_spec.rb +13 -0
- data/spec/timeouts/timings_spec.rb +55 -0
- metadata +527 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC do
|
|
6
|
+
context 'interceptor' do
|
|
7
|
+
before(:each) do
|
|
8
|
+
class Services
|
|
9
|
+
def self.timing(_path, _time); end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class StatsTimingInterceptor < DHC::Interceptor
|
|
13
|
+
def after_response
|
|
14
|
+
uri = URI.parse(response.request.url)
|
|
15
|
+
path = [
|
|
16
|
+
'web',
|
|
17
|
+
((ActiveSupport.gem_version >= Gem::Version.new('6.0.0')) ? Rails.application.class.module_parent_name : Rails.application.class.parent_name).underscore,
|
|
18
|
+
Rails.env,
|
|
19
|
+
response.request.method,
|
|
20
|
+
uri.scheme,
|
|
21
|
+
uri.host,
|
|
22
|
+
response.code
|
|
23
|
+
].join('.')
|
|
24
|
+
Services.timing(path.downcase, response.time)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
DHC.configure { |c| c.interceptors = [StatsTimingInterceptor] }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
let(:url) { 'http://depay.fi/v2/feedbacks/-Sc4_pYNpqfsudzhtivfkA' }
|
|
31
|
+
|
|
32
|
+
it 'can take action after a response was received' do
|
|
33
|
+
allow(Services).to receive(:timing).with('web.dummy.test.get.http.depay.fi.200', 0)
|
|
34
|
+
stub_request(:get, url)
|
|
35
|
+
DHC.get(url)
|
|
36
|
+
expect(Services).to have_received(:timing)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Auth do
|
|
6
|
+
before(:each) do
|
|
7
|
+
DHC.config.interceptors = [DHC::Auth]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'adds basic auth to every request' do
|
|
11
|
+
options = { basic: { username: 'steve', password: 'can' } }
|
|
12
|
+
DHC.config.endpoint(:local, 'http://depay.fi', auth: options)
|
|
13
|
+
stub_request(:get, 'http://depay.fi')
|
|
14
|
+
.with(headers: { 'Authorization' => 'Basic c3RldmU6Y2Fu' })
|
|
15
|
+
DHC.get(:local)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Auth do
|
|
6
|
+
before(:each) do
|
|
7
|
+
DHC.config.interceptors = [DHC::Auth]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'adds the bearer token to every request' do
|
|
11
|
+
def bearer_token
|
|
12
|
+
'123456'
|
|
13
|
+
end
|
|
14
|
+
options = { bearer: -> { bearer_token } }
|
|
15
|
+
DHC.config.endpoint(:local, 'http://depay.fi', auth: options)
|
|
16
|
+
stub_request(:get, 'http://depay.fi').with(headers: { 'Authorization' => 'Bearer 123456' })
|
|
17
|
+
DHC.get(:local)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Auth do
|
|
6
|
+
before(:each) do
|
|
7
|
+
DHC.config.interceptors = [DHC::Auth]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'adds body authentication to the existing request body' do
|
|
11
|
+
stub_request(:post, 'http://depay.fi/')
|
|
12
|
+
.with(body: {
|
|
13
|
+
message: 'body',
|
|
14
|
+
userToken: 'dheur5hrk3'
|
|
15
|
+
}.to_json)
|
|
16
|
+
|
|
17
|
+
DHC.post('http://depay.fi', auth: { body: { userToken: 'dheur5hrk3' } }, body: {
|
|
18
|
+
message: 'body'
|
|
19
|
+
})
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'adds body authentication to an empty request body' do
|
|
23
|
+
stub_request(:post, 'http://depay.fi/')
|
|
24
|
+
.with(body: {
|
|
25
|
+
userToken: 'dheur5hrk3'
|
|
26
|
+
}.to_json)
|
|
27
|
+
|
|
28
|
+
DHC.post('http://depay.fi', auth: { body: { userToken: 'dheur5hrk3' } })
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'adds nothing if request method is GET' do
|
|
32
|
+
stub_request(:get, 'http://depay.fi/')
|
|
33
|
+
|
|
34
|
+
DHC.get('http://depay.fi', auth: { body: { userToken: 'dheur5hrk3' } })
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Auth do
|
|
6
|
+
before(:each) do
|
|
7
|
+
DHC.config.interceptors = [DHC::Auth]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'adds basic auth in a correct way even if username and password are especially long' do
|
|
11
|
+
options = { basic: { username: '123456789101234', password: '12345678901234567890123456789012' } }
|
|
12
|
+
DHC.config.endpoint(:local, 'http://depay.fi', auth: options)
|
|
13
|
+
stub_request(:get, 'http://depay.fi')
|
|
14
|
+
.with(headers: { 'Authorization' => 'Basic MTIzNDU2Nzg5MTAxMjM0OjEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEy' })
|
|
15
|
+
DHC.get(:local)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Auth do
|
|
6
|
+
before(:each) do
|
|
7
|
+
class AuthPrepInterceptor < DHC::Interceptor
|
|
8
|
+
|
|
9
|
+
def before_request
|
|
10
|
+
request.options[:auth] = { bearer: 'sometoken' }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
DHC.config.interceptors = [AuthPrepInterceptor, DHC::Auth]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
after do
|
|
18
|
+
DHC.config.reset
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'does not use instance variables internally so that other interceptors can still change auth options' do
|
|
22
|
+
stub_request(:get, 'http://depay.fi/')
|
|
23
|
+
.with(headers: { 'Authorization' => 'Bearer sometoken' })
|
|
24
|
+
.to_return(status: 200)
|
|
25
|
+
DHC.get('http://depay.fi')
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Auth do
|
|
6
|
+
let(:bearer_token) { '123456' }
|
|
7
|
+
|
|
8
|
+
before(:each) do
|
|
9
|
+
stub_request(:get, 'http://depay.fi').with(headers: { 'Authorization' => "Bearer #{bearer_token}" })
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
context 'configuration check not happening' do
|
|
13
|
+
let(:options) { { bearer: bearer_token } }
|
|
14
|
+
|
|
15
|
+
before(:each) { DHC.config.interceptors = [DHC::Auth, DHC::Retry] }
|
|
16
|
+
|
|
17
|
+
it 'max_recovery_attempts is zero' do
|
|
18
|
+
expect_any_instance_of(described_class).not_to receive(:warn)
|
|
19
|
+
DHC.config.endpoint(:local, 'http://depay.fi', auth: options.merge(max_recovery_attempts: 0))
|
|
20
|
+
DHC.get(:local)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'max_recovery_attempts is missing' do
|
|
24
|
+
expect_any_instance_of(described_class).not_to receive(:warn)
|
|
25
|
+
DHC.config.endpoint(:local, 'http://depay.fi', auth: options)
|
|
26
|
+
DHC.get(:local)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'configuration check happening' do
|
|
31
|
+
let(:options) { { bearer: bearer_token, max_recovery_attempts: 1, refresh_client_token: -> { 'here comes your refresh code' } } }
|
|
32
|
+
|
|
33
|
+
it 'no warning with proper options' do
|
|
34
|
+
DHC.config.interceptors = [DHC::Auth, DHC::Retry]
|
|
35
|
+
DHC.config.endpoint(:local, 'http://depay.fi', auth: options)
|
|
36
|
+
expect_any_instance_of(described_class).not_to receive(:warn)
|
|
37
|
+
DHC.get(:local)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'warn refresh_client_token is a string' do
|
|
41
|
+
DHC.config.interceptors = [DHC::Auth, DHC::Retry]
|
|
42
|
+
DHC.config.endpoint(:local, 'http://depay.fi', auth: options.merge(refresh_client_token: bearer_token))
|
|
43
|
+
expect_any_instance_of(described_class).to receive(:warn).with('[WARNING] The given refresh_client_token must be a Proc for reauthentication.')
|
|
44
|
+
DHC.get(:local)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'warn interceptors miss DHC::Retry' do
|
|
48
|
+
DHC.config.interceptors = [DHC::Auth]
|
|
49
|
+
DHC.config.endpoint(:local, 'http://depay.fi', auth: options)
|
|
50
|
+
expect_any_instance_of(described_class).to receive(:warn).with('[WARNING] Your interceptors must include DHC::Retry after DHC::Auth.')
|
|
51
|
+
DHC.get(:local)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'warn interceptors DHC::Retry before DHC::Auth' do
|
|
55
|
+
DHC.config.interceptors = [DHC::Retry, DHC::Auth]
|
|
56
|
+
DHC.config.endpoint(:local, 'http://depay.fi', auth: options)
|
|
57
|
+
expect_any_instance_of(described_class).to receive(:warn).with('[WARNING] Your interceptors must include DHC::Retry after DHC::Auth.')
|
|
58
|
+
DHC.get(:local)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Auth do
|
|
6
|
+
let(:initial_token) { '123456' }
|
|
7
|
+
let(:refresh_token) { 'abcdef' }
|
|
8
|
+
let(:options) { { bearer: initial_token, refresh_client_token: -> { refresh_token } } }
|
|
9
|
+
let!(:auth_failing) do
|
|
10
|
+
stub_request(:get, 'http://depay.fi')
|
|
11
|
+
.with(headers: { 'Authorization' => "Bearer #{initial_token}" })
|
|
12
|
+
.to_return(status: 401, body: '{}') # DHC::Unauthorized
|
|
13
|
+
end
|
|
14
|
+
let!(:auth_suceeding_after_recovery) do
|
|
15
|
+
stub_request(:get, 'http://depay.fi')
|
|
16
|
+
.with(headers: { 'Authorization' => "Bearer #{refresh_token}" })
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
before(:each) do
|
|
20
|
+
DHC.config.interceptors = [DHC::Auth, DHC::Retry]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'recovery is attempted' do
|
|
24
|
+
DHC.config.endpoint(:local, 'http://depay.fi', auth: options)
|
|
25
|
+
# the retried request (with updated Bearer), that should work
|
|
26
|
+
DHC.get(:local)
|
|
27
|
+
expect(auth_suceeding_after_recovery).to have_been_made.once
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'recovery is not attempted again when the request has reauthenticated: true ' do
|
|
31
|
+
DHC.config.endpoint(:local, 'http://depay.fi', auth: options.merge(reauthenticated: true))
|
|
32
|
+
expect { DHC.get(:local) }.to raise_error(DHC::Unauthorized)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context 'token format' do
|
|
36
|
+
let(:initial_token) { 'BAsZ-98-ZZZ' }
|
|
37
|
+
|
|
38
|
+
it 'refreshes tokens with various formats' do
|
|
39
|
+
DHC.config.endpoint(:local, 'http://depay.fi', auth: options)
|
|
40
|
+
DHC.get(:local)
|
|
41
|
+
expect(auth_suceeding_after_recovery).to have_been_made.once
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC do
|
|
6
|
+
context 'interceptor' do
|
|
7
|
+
before(:each) do
|
|
8
|
+
class TrackingIdInterceptor < DHC::Interceptor
|
|
9
|
+
def before_request
|
|
10
|
+
request.params[:tid] = 123
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
DHC.configure { |c| c.interceptors = [TrackingIdInterceptor] }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'can modify requests before they are send' do
|
|
17
|
+
stub_request(:get, 'http://depay.fi/?tid=123')
|
|
18
|
+
DHC.get('http://depay.fi')
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC do
|
|
6
|
+
context 'interceptor' do
|
|
7
|
+
before(:each) do
|
|
8
|
+
class SomeInterceptor < DHC::Interceptor
|
|
9
|
+
def before_response; end
|
|
10
|
+
end
|
|
11
|
+
DHC.configure { |c| c.interceptors = [SomeInterceptor] }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'can perform some actions before a reponse is received' do
|
|
15
|
+
expect_any_instance_of(SomeInterceptor).to receive(:before_response)
|
|
16
|
+
stub_request(:get, 'http://depay.fi')
|
|
17
|
+
DHC.get('http://depay.fi')
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Caching do
|
|
6
|
+
before(:each) do
|
|
7
|
+
DHC.config.interceptors = [DHC::Caching]
|
|
8
|
+
DHC::Caching.cache = Rails.cache
|
|
9
|
+
Rails.cache.clear
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let!(:first_request) do
|
|
13
|
+
stub_request(:get, 'http://depay.fi/').to_return(body: 'Website')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
let!(:second_request) do
|
|
17
|
+
stub_request(:get, 'http://depay.fi/weather').to_return(body: 'The weather')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'does not fetch requests served from cache when doing requests in parallel with hydra' do
|
|
21
|
+
DHC.request([{ url: 'http://depay.fi', cache: true }, { url: 'http://depay.fi/weather', cache: true }])
|
|
22
|
+
DHC.request([{ url: 'http://depay.fi', cache: true }, { url: 'http://depay.fi/weather', cache: true }])
|
|
23
|
+
assert_requested first_request, times: 1
|
|
24
|
+
assert_requested second_request, times: 1
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Caching do
|
|
6
|
+
before(:each) do
|
|
7
|
+
DHC.config.interceptors = [DHC::Caching]
|
|
8
|
+
DHC::Caching.cache = Rails.cache
|
|
9
|
+
Rails.cache.clear
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let(:stub) { stub_request(:get, 'http://depay.fi').to_return(status: 200, body: 'The Website') }
|
|
13
|
+
|
|
14
|
+
it 'serves a response from cache' do
|
|
15
|
+
stub
|
|
16
|
+
DHC.config.endpoint(:local, 'http://depay.fi', cache: { expires_in: 5.minutes })
|
|
17
|
+
expect(Rails.cache).to receive(:write)
|
|
18
|
+
.with(
|
|
19
|
+
"DHC_CACHE(v#{DHC::Caching::CACHE_VERSION}): GET http://depay.fi",
|
|
20
|
+
{
|
|
21
|
+
body: 'The Website',
|
|
22
|
+
code: 200,
|
|
23
|
+
headers: nil,
|
|
24
|
+
return_code: nil,
|
|
25
|
+
mock: :webmock
|
|
26
|
+
}, { expires_in: 5.minutes }
|
|
27
|
+
)
|
|
28
|
+
.and_call_original
|
|
29
|
+
original_response = DHC.get(:local)
|
|
30
|
+
cached_response = DHC.get(:local)
|
|
31
|
+
expect(original_response.body).to eq cached_response.body
|
|
32
|
+
expect(original_response.code).to eq cached_response.code
|
|
33
|
+
expect(original_response.headers).to eq cached_response.headers
|
|
34
|
+
expect(original_response.options[:return_code]).to eq cached_response.options[:return_code]
|
|
35
|
+
expect(original_response.mock).to eq cached_response.mock
|
|
36
|
+
assert_requested stub, times: 1
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'does not serve from cache if option is not set' do
|
|
40
|
+
DHC.config.endpoint(:local, 'http://depay.fi')
|
|
41
|
+
expect(Rails.cache).not_to receive(:write)
|
|
42
|
+
expect(Rails.cache).not_to receive(:fetch)
|
|
43
|
+
stub
|
|
44
|
+
2.times { DHC.get(:local) }
|
|
45
|
+
assert_requested stub, times: 2
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'lets you configure the cache key that will be used' do
|
|
49
|
+
DHC.config.endpoint(:local, 'http://depay.fi', cache: { key: 'STATICKEY' })
|
|
50
|
+
expect(Rails.cache).to receive(:fetch).at_least(:once).with("DHC_CACHE(v#{DHC::Caching::CACHE_VERSION}): STATICKEY").and_call_original
|
|
51
|
+
expect(Rails.cache).to receive(:write).with("DHC_CACHE(v#{DHC::Caching::CACHE_VERSION}): STATICKEY", anything, anything).and_call_original
|
|
52
|
+
stub
|
|
53
|
+
DHC.get(:local)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'does not store server errors in cache' do
|
|
57
|
+
DHC.config.endpoint(:local, 'http://depay.fi', cache: true)
|
|
58
|
+
stub_request(:get, 'http://depay.fi').to_return(status: 500, body: 'ERROR')
|
|
59
|
+
expect { DHC.get(:local) }.to raise_error DHC::ServerError
|
|
60
|
+
stub
|
|
61
|
+
expect(Rails.cache).to receive(:write).once
|
|
62
|
+
DHC.get(:local)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'marks response not from cache as not served from cache and from cache as served from cache' do
|
|
66
|
+
stub
|
|
67
|
+
DHC.config.endpoint(:local, 'http://depay.fi', cache: true)
|
|
68
|
+
original_response = DHC.get(:local)
|
|
69
|
+
expect(original_response.from_cache?).to eq false
|
|
70
|
+
cached_response = DHC.get(:local)
|
|
71
|
+
expect(cached_response.from_cache?).to eq true
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Caching do
|
|
6
|
+
before(:each) do
|
|
7
|
+
DHC.config.interceptors = [DHC::Caching]
|
|
8
|
+
DHC::Caching.cache = Rails.cache
|
|
9
|
+
Rails.cache.clear
|
|
10
|
+
|
|
11
|
+
DHC.config.endpoint(:local, 'http://depay.fi', cache: { expires_in: 5.minutes })
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
let!(:stub) { stub_request(:post, 'http://depay.fi').to_return(status: 200, body: 'The Website') }
|
|
15
|
+
|
|
16
|
+
it 'only caches GET requests by default' do
|
|
17
|
+
expect(Rails.cache).not_to receive(:write)
|
|
18
|
+
DHC.post(:local)
|
|
19
|
+
assert_requested stub, times: 1
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'also caches other methods, when explicitly enabled' do
|
|
23
|
+
expect(Rails.cache).to receive(:write)
|
|
24
|
+
.with(
|
|
25
|
+
"DHC_CACHE(v#{DHC::Caching::CACHE_VERSION}): POST http://depay.fi",
|
|
26
|
+
{
|
|
27
|
+
body: 'The Website',
|
|
28
|
+
code: 200,
|
|
29
|
+
headers: nil,
|
|
30
|
+
return_code: nil,
|
|
31
|
+
mock: :webmock
|
|
32
|
+
}, { expires_in: 5.minutes }
|
|
33
|
+
)
|
|
34
|
+
.and_call_original
|
|
35
|
+
original_response = DHC.post(:local, cache: { methods: [:post] })
|
|
36
|
+
cached_response = DHC.post(:local, cache: { methods: [:post] })
|
|
37
|
+
expect(original_response.body).to eq cached_response.body
|
|
38
|
+
expect(original_response.code).to eq cached_response.code
|
|
39
|
+
expect(original_response.headers).to eq cached_response.headers
|
|
40
|
+
assert_requested stub, times: 1
|
|
41
|
+
end
|
|
42
|
+
end
|