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,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Caching do
|
|
6
|
+
let(:redis_url) { 'redis://localhost:6379/0' }
|
|
7
|
+
let(:redis_cache) do
|
|
8
|
+
spy('ActiveSupport::Cache::RedisCacheStore')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
before do
|
|
12
|
+
Rails.cache.clear
|
|
13
|
+
DHC.config.interceptors = [DHC::Caching]
|
|
14
|
+
ActiveSupport::Cache::RedisCacheStore.new(url: redis_url).clear
|
|
15
|
+
allow(ActiveSupport::Cache::RedisCacheStore).to receive(:new).and_return(redis_cache)
|
|
16
|
+
allow(redis_cache).to receive(:present?).and_return(true)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
let!(:request_stub) do
|
|
20
|
+
stub_request(:get, 'http://depay.fi/')
|
|
21
|
+
.to_return(body: '<h1>Hi there</h1>')
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def request
|
|
25
|
+
DHC.get('http://depay.fi', cache: true)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def response_has_been_cached_and_served_from_cache!
|
|
29
|
+
original_response = request
|
|
30
|
+
cached_response = request
|
|
31
|
+
|
|
32
|
+
expect(original_response.body).to eq cached_response.body
|
|
33
|
+
expect(original_response.code).to eq cached_response.code
|
|
34
|
+
expect(original_response.headers).to eq cached_response.headers
|
|
35
|
+
expect(original_response.options[:return_code]).to eq cached_response.options[:return_code]
|
|
36
|
+
expect(original_response.mock).to eq cached_response.mock
|
|
37
|
+
|
|
38
|
+
assert_requested request_stub, times: 1
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context 'only local cache has been configured' do
|
|
42
|
+
before do
|
|
43
|
+
DHC::Caching.cache = Rails.cache
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'serves a response from local cache without trying the central cache' do
|
|
47
|
+
expect(Rails.cache).to receive(:fetch).at_least(:once).and_call_original
|
|
48
|
+
expect(Rails.cache).to receive(:write).and_call_original
|
|
49
|
+
expect(-> { response_has_been_cached_and_served_from_cache! })
|
|
50
|
+
.to output(%{[DHC] served from local cache: "DHC_CACHE(v1): GET http://depay.fi"\n}).to_stdout
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context 'local and central cache have been configured' do
|
|
55
|
+
before do
|
|
56
|
+
DHC::Caching.cache = Rails.cache
|
|
57
|
+
DHC::Caching.central = {
|
|
58
|
+
read: redis_url,
|
|
59
|
+
write: redis_url
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context 'found in central cache' do
|
|
64
|
+
it 'serves it from central cache if found there' do
|
|
65
|
+
expect(redis_cache).to receive(:fetch).and_return(nil,
|
|
66
|
+
body: '<h1>Hi there</h1>', code: 200, headers: nil, return_code: nil, mock: :webmock)
|
|
67
|
+
expect(redis_cache).to receive(:write).and_return(true)
|
|
68
|
+
expect(Rails.cache).to receive(:fetch).and_call_original
|
|
69
|
+
expect(Rails.cache).to receive(:write).and_call_original
|
|
70
|
+
expect(-> { response_has_been_cached_and_served_from_cache! })
|
|
71
|
+
.to output(%{[DHC] served from central cache: "DHC_CACHE(v1): GET http://depay.fi"\n}).to_stdout
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
context 'not found in central cache' do
|
|
76
|
+
it 'serves it from local cache if found there' do
|
|
77
|
+
expect(redis_cache).to receive(:fetch).and_return(nil, nil)
|
|
78
|
+
expect(redis_cache).to receive(:write).and_return(true)
|
|
79
|
+
expect(Rails.cache).to receive(:fetch).at_least(:once).and_call_original
|
|
80
|
+
expect(Rails.cache).to receive(:write).and_call_original
|
|
81
|
+
expect(-> { response_has_been_cached_and_served_from_cache! })
|
|
82
|
+
.to output(%{[DHC] served from local cache: "DHC_CACHE(v1): GET http://depay.fi"\n}).to_stdout
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
context 'only central read configured' do
|
|
88
|
+
before do
|
|
89
|
+
DHC::Caching.cache = Rails.cache
|
|
90
|
+
DHC::Caching.central = {
|
|
91
|
+
read: redis_url
|
|
92
|
+
}
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'still serves responses from cache, but does not write them back' do
|
|
96
|
+
expect(redis_cache).to receive(:fetch).and_return(nil, body: '<h1>Hi there</h1>', code: 200, headers: nil, return_code: nil, mock: :webmock)
|
|
97
|
+
expect(redis_cache).not_to receive(:write)
|
|
98
|
+
expect(Rails.cache).to receive(:fetch).and_call_original
|
|
99
|
+
expect(Rails.cache).to receive(:write).and_call_original
|
|
100
|
+
expect(-> { response_has_been_cached_and_served_from_cache! })
|
|
101
|
+
.to output(%{[DHC] served from central cache: "DHC_CACHE(v1): GET http://depay.fi"\n}).to_stdout
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
context 'only central write configured' do
|
|
106
|
+
before do
|
|
107
|
+
DHC::Caching.cache = Rails.cache
|
|
108
|
+
DHC::Caching.central = {
|
|
109
|
+
write: redis_url
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'still writes responses to cache, but does not retrieve them from there' do
|
|
114
|
+
expect(redis_cache).not_to receive(:fetch)
|
|
115
|
+
expect(redis_cache).to receive(:write).and_return(true)
|
|
116
|
+
expect(Rails.cache).to receive(:fetch).at_least(:once).and_call_original
|
|
117
|
+
expect(Rails.cache).to receive(:write).and_call_original
|
|
118
|
+
expect(-> { response_has_been_cached_and_served_from_cache! })
|
|
119
|
+
.to output(%{[DHC] served from local cache: "DHC_CACHE(v1): GET http://depay.fi"\n}).to_stdout
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
context 'central cache configured only' do
|
|
124
|
+
before do
|
|
125
|
+
DHC::Caching.cache = nil
|
|
126
|
+
DHC::Caching.central = {
|
|
127
|
+
read: redis_url,
|
|
128
|
+
write: redis_url
|
|
129
|
+
}
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it 'does not inquire the local cache for information neither to write them' do
|
|
133
|
+
expect(redis_cache).to receive(:fetch).and_return(nil, body: '<h1>Hi there</h1>', code: 200, headers: nil, return_code: nil, mock: :webmock)
|
|
134
|
+
expect(redis_cache).to receive(:write).and_return(true)
|
|
135
|
+
expect(-> { response_has_been_cached_and_served_from_cache! })
|
|
136
|
+
.to output(%{[DHC] served from central cache: "DHC_CACHE(v1): GET http://depay.fi"\n}).to_stdout
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
# due to the fact that options passed into DHC get dup'ed
|
|
6
|
+
# we need a class where we can setup method expectations
|
|
7
|
+
# with `expect_any_instance`
|
|
8
|
+
class CacheMock
|
|
9
|
+
def fetch(*_); end
|
|
10
|
+
|
|
11
|
+
def write(*_); end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe DHC::Caching do
|
|
15
|
+
let(:default_cache) { DHC::Caching.cache }
|
|
16
|
+
|
|
17
|
+
before(:each) do
|
|
18
|
+
stub_request(:get, 'http://depay.fi').to_return(status: 200, body: 'The Website')
|
|
19
|
+
DHC.config.interceptors = [DHC::Caching]
|
|
20
|
+
default_cache.clear
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'does cache' do
|
|
24
|
+
expect(default_cache).to receive(:fetch)
|
|
25
|
+
expect(default_cache).to receive(:write)
|
|
26
|
+
DHC.get('http://depay.fi', cache: true)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'does not cache' do
|
|
30
|
+
expect(default_cache).not_to receive(:fetch)
|
|
31
|
+
expect(default_cache).not_to receive(:write)
|
|
32
|
+
DHC.get('http://depay.fi')
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context 'options - directly via DHC.get' do
|
|
36
|
+
it 'uses the default cache' do
|
|
37
|
+
expect(default_cache).to receive(:fetch)
|
|
38
|
+
expect(default_cache).to receive(:write)
|
|
39
|
+
DHC.get('http://depay.fi', cache: true)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'uses the provided cache' do
|
|
43
|
+
expect_any_instance_of(CacheMock).to receive(:fetch)
|
|
44
|
+
expect_any_instance_of(CacheMock).to receive(:write)
|
|
45
|
+
DHC.get('http://depay.fi', cache: { use: CacheMock.new })
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'cache options are properly forwarded to the cache' do
|
|
49
|
+
cache_options = { expires_in: 5.minutes, race_condition_ttl: 15.seconds }
|
|
50
|
+
expect(default_cache).to receive(:write).with(anything, anything, cache_options)
|
|
51
|
+
DHC.get('http://depay.fi', cache: cache_options)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context 'options - via endpoint configuration' do
|
|
56
|
+
it 'uses the default cache' do
|
|
57
|
+
DHC.config.endpoint(:local, 'http://depay.fi', cache: true)
|
|
58
|
+
expect(default_cache).to receive(:fetch)
|
|
59
|
+
expect(default_cache).to receive(:write)
|
|
60
|
+
DHC.get(:local)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'uses the provided cache' do
|
|
64
|
+
options = { cache: { use: CacheMock.new } }
|
|
65
|
+
DHC.config.endpoint(:local, 'http://depay.fi', options)
|
|
66
|
+
expect_any_instance_of(CacheMock).to receive(:fetch)
|
|
67
|
+
expect_any_instance_of(CacheMock).to receive(:write)
|
|
68
|
+
DHC.get(:local)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'cache options are properly forwarded to the cache' do
|
|
72
|
+
cache_options = { expires_in: 5.minutes, race_condition_ttl: 15.seconds }
|
|
73
|
+
DHC.config.endpoint(:local, 'http://depay.fi', cache: cache_options)
|
|
74
|
+
expect(default_cache).to receive(:write).with(anything, anything, cache_options)
|
|
75
|
+
DHC.get(:local)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Caching do
|
|
6
|
+
context 'parameters' do
|
|
7
|
+
before(:each) do
|
|
8
|
+
DHC.config.interceptors = [DHC::Caching]
|
|
9
|
+
Rails.cache.clear
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'considers parameters when writing/reading from cache' do
|
|
13
|
+
DHC.config.endpoint(:local, 'http://depay.fi', cache: true)
|
|
14
|
+
stub_request(:get, 'http://depay.fi').to_return(status: 200, body: 'The Website')
|
|
15
|
+
stub_request(:get, 'http://depay.fi?location=zuerich').to_return(status: 200, body: 'The Website for Zuerich')
|
|
16
|
+
expect(
|
|
17
|
+
DHC.get(:local).body
|
|
18
|
+
).to eq 'The Website'
|
|
19
|
+
expect(
|
|
20
|
+
DHC.get(:local, params: { location: 'zuerich' }).body
|
|
21
|
+
).to eq 'The Website for Zuerich'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
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.config.endpoint(:local, 'http://depay.fi', cache: true)
|
|
9
|
+
Rails.cache.clear
|
|
10
|
+
# leverage the Typhoeus internal mock attribute in order to get Typhoeus evaluate the return_code
|
|
11
|
+
# lib/typhoeus/response/status.rb:48
|
|
12
|
+
allow_any_instance_of(Typhoeus::Response).to receive(:mock).and_return(false)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
let!(:stub) { stub_request(:get, 'http://depay.fi').to_return(status: 200, body: 'The Website') }
|
|
16
|
+
|
|
17
|
+
it 'provides the correct response status for responses from cache' do
|
|
18
|
+
stub
|
|
19
|
+
# the real request provides the return_code
|
|
20
|
+
allow_any_instance_of(Typhoeus::Response).to receive(:options)
|
|
21
|
+
.and_return(code: 200, status_message: '', body: 'The Website', headers: nil, return_code: :ok)
|
|
22
|
+
response = DHC.get(:local)
|
|
23
|
+
expect(response.success?).to eq true
|
|
24
|
+
# the cached response should get it from the cache
|
|
25
|
+
allow_any_instance_of(Typhoeus::Response).to receive(:options).and_call_original
|
|
26
|
+
cached_response = DHC.get(:local)
|
|
27
|
+
expect(cached_response.success?).to eq true
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Caching do
|
|
6
|
+
context 'to_cache' do
|
|
7
|
+
it 'returns a marshalable object to store in the cache' do
|
|
8
|
+
expect do
|
|
9
|
+
response = Typhoeus::Response.new(headers: { 'Accept' => 'application/json' })
|
|
10
|
+
Marshal.dump(
|
|
11
|
+
DHC::Caching.new(response).send(:to_cache, response)
|
|
12
|
+
)
|
|
13
|
+
end.not_to raise_error
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC do
|
|
6
|
+
context 'default interceptors' do
|
|
7
|
+
before(:each) do
|
|
8
|
+
DHC.configure {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'alwayses return a list for default interceptors' do
|
|
12
|
+
expect(DHC.config.interceptors).to eq []
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::DefaultTimeout do
|
|
6
|
+
before(:each) do
|
|
7
|
+
DHC.config.interceptors = [DHC::DefaultTimeout]
|
|
8
|
+
DHC::DefaultTimeout.timeout = nil
|
|
9
|
+
DHC::DefaultTimeout.connecttimeout = nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let(:stub) { stub_request(:get, 'http://depay.fi').to_return(status: 200, body: 'The Website') }
|
|
13
|
+
|
|
14
|
+
it 'applies default timeouts to all requests made' do
|
|
15
|
+
stub
|
|
16
|
+
expect_any_instance_of(Ethon::Easy).to receive(:http_request)
|
|
17
|
+
.with(anything, anything, hash_including(timeout: 15, connecttimeout: 2)).and_call_original
|
|
18
|
+
DHC.get('http://depay.fi')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context 'with changed default timesouts' do
|
|
22
|
+
before(:each) do
|
|
23
|
+
DHC::DefaultTimeout.timeout = 10
|
|
24
|
+
DHC::DefaultTimeout.connecttimeout = 3
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'applies custom default timeouts to all requests made' do
|
|
28
|
+
stub
|
|
29
|
+
expect_any_instance_of(Ethon::Easy).to receive(:http_request)
|
|
30
|
+
.with(anything, anything, hash_including(timeout: 10, connecttimeout: 3)).and_call_original
|
|
31
|
+
DHC.get('http://depay.fi')
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
end
|
|
10
|
+
|
|
11
|
+
class AnotherInterceptor < DHC::Interceptor
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'performs interceptor when they are set globally' do
|
|
16
|
+
DHC.configure { |c| c.interceptors = [SomeInterceptor] }
|
|
17
|
+
expect_any_instance_of(SomeInterceptor).to receive(:before_request)
|
|
18
|
+
stub_request(:get, 'http://depay.fi')
|
|
19
|
+
DHC.get('http://depay.fi')
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'overrides interceptors on request level' do
|
|
23
|
+
DHC.configure { |c| c.interceptors = [SomeInterceptor] }
|
|
24
|
+
expect_any_instance_of(AnotherInterceptor).to receive(:before_request)
|
|
25
|
+
expect_any_instance_of(SomeInterceptor).not_to receive(:before_request)
|
|
26
|
+
stub_request(:get, 'http://depay.fi')
|
|
27
|
+
DHC.get('http://depay.fi', interceptors: [AnotherInterceptor])
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'does not dup' do
|
|
13
|
+
options = { interceptors: [SomeInterceptor] }
|
|
14
|
+
expect(
|
|
15
|
+
options.deep_dup[:interceptors].include?(SomeInterceptor)
|
|
16
|
+
).to eq true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Logging do
|
|
6
|
+
let(:logger) { spy('logger') }
|
|
7
|
+
|
|
8
|
+
before(:each) do
|
|
9
|
+
DHC.config.interceptors = [DHC::Logging]
|
|
10
|
+
DHC::Logging.logger = logger
|
|
11
|
+
stub_request(:get, 'http://depay.fi').to_return(status: 200)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'does log information before and after every request made with DHC' do
|
|
15
|
+
DHC.get('http://depay.fi')
|
|
16
|
+
expect(logger).to have_received(:info).once.with(
|
|
17
|
+
%r{Before DHC request <\d+> GET http://depay.fi at \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2} Params={} Headers={.*?}}
|
|
18
|
+
)
|
|
19
|
+
expect(logger).to have_received(:info).once.with(
|
|
20
|
+
%r{After DHC response for request <\d+> GET http://depay.fi at \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2} Time=0ms URL=http://depay.fi:80/}
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'source' do
|
|
25
|
+
let(:source) { '/Users/Sebastian/DHC/test.rb' }
|
|
26
|
+
|
|
27
|
+
it 'does log the source if provided as option' do
|
|
28
|
+
DHC.get('http://depay.fi', source: source)
|
|
29
|
+
expect(logger).to have_received(:info).once.with(
|
|
30
|
+
%r{Before DHC request <\d+> GET http://depay.fi at \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2} Params={} Headers={.*?} \nCalled from #{source}}
|
|
31
|
+
)
|
|
32
|
+
expect(logger).to have_received(:info).once.with(
|
|
33
|
+
%r{After DHC response for request <\d+> GET http://depay.fi at \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2} Time=0ms URL=http://depay.fi:80/ \nCalled from #{source}}
|
|
34
|
+
)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe DHC::Monitoring do
|
|
6
|
+
let(:stub) do
|
|
7
|
+
stub_request(:get, 'http://depay.fi').to_return(status: 200, body: 'The Website')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module Statsd
|
|
11
|
+
def self.count(_path, _value); end
|
|
12
|
+
|
|
13
|
+
def self.timing(_path, _value); end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
before(:each) do
|
|
17
|
+
DHC::Monitoring.statsd = Statsd
|
|
18
|
+
Rails.cache.clear
|
|
19
|
+
allow(Statsd).to receive(:count).with('dhc.dummy.test.depay_fi.get.before_request', 1)
|
|
20
|
+
allow(Statsd).to receive(:count).with('dhc.dummy.test.depay_fi.get.count', 1)
|
|
21
|
+
allow(Statsd).to receive(:count).with('dhc.dummy.test.depay_fi.get.after_request', 1)
|
|
22
|
+
allow(Statsd).to receive(:count).with('dhc.dummy.test.depay_fi.get.200', 1)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context 'interceptors configured correctly' do
|
|
26
|
+
before do
|
|
27
|
+
DHC.config.interceptors = [DHC::Caching, DHC::Monitoring]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'requesting with cache option' do
|
|
31
|
+
it 'monitors miss/hit for caching' do
|
|
32
|
+
stub
|
|
33
|
+
expect(Statsd).to receive(:count).with('dhc.dummy.test.depay_fi.get.cache.miss', 1)
|
|
34
|
+
expect(Statsd).to receive(:count).with('dhc.dummy.test.depay_fi.get.cache.hit', 1)
|
|
35
|
+
DHC.get('http://depay.fi', cache: true)
|
|
36
|
+
DHC.get('http://depay.fi', cache: true)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context 'request uncached' do
|
|
41
|
+
it 'requesting without cache option' do
|
|
42
|
+
stub
|
|
43
|
+
expect(Statsd).not_to receive(:count).with('dhc.dummy.test.depay_fi.get.cache.miss', 1)
|
|
44
|
+
expect(Statsd).not_to receive(:count).with('dhc.dummy.test.depay_fi.get.cache.hit', 1)
|
|
45
|
+
DHC.get('http://depay.fi')
|
|
46
|
+
DHC.get('http://depay.fi')
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context 'wrong interceptor order' do
|
|
52
|
+
before(:each) do
|
|
53
|
+
DHC.config.interceptors = [DHC::Monitoring, DHC::Caching] # monitoring needs to be after Caching
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'does monitors miss/hit for caching and warns about wrong order of interceptors' do
|
|
57
|
+
stub
|
|
58
|
+
expect(Statsd).not_to receive(:count).with('dhc.dummy.test.depay_fi.get.cache.miss', 1)
|
|
59
|
+
expect(Statsd).not_to receive(:count).with('dhc.dummy.test.depay_fi.get.cache.hit', 1)
|
|
60
|
+
expect(-> {
|
|
61
|
+
DHC.get('http://depay.fi', cache: true)
|
|
62
|
+
DHC.get('http://depay.fi', cache: true)
|
|
63
|
+
}).to output("[WARNING] Your interceptors must include DHC::Caching and DHC::Monitoring and also in that order.\n[WARNING] Your interceptors must include DHC::Caching and DHC::Monitoring and also in that order.\n").to_stderr
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|