lhc 12.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/.gitignore +37 -0
- data/.rubocop.localch.yml +325 -0
- data/.rubocop.yml +61 -0
- data/.ruby-version +1 -0
- data/Gemfile +13 -0
- data/Gemfile.activesupport4 +4 -0
- data/Gemfile.activesupport5 +4 -0
- data/Gemfile.activesupport6 +4 -0
- data/LICENSE +674 -0
- data/README.md +984 -0
- data/Rakefile +25 -0
- data/cider-ci.yml +6 -0
- data/cider-ci/bin/bundle +51 -0
- data/cider-ci/bin/ruby_install +8 -0
- data/cider-ci/bin/ruby_version +25 -0
- data/cider-ci/jobs/rspec-activesupport-4.yml +28 -0
- data/cider-ci/jobs/rspec-activesupport-5.yml +27 -0
- data/cider-ci/jobs/rspec-activesupport-6.yml +28 -0
- data/cider-ci/jobs/rubocop.yml +18 -0
- data/cider-ci/task_components/bundle.yml +22 -0
- data/cider-ci/task_components/rspec.yml +36 -0
- data/cider-ci/task_components/rubocop.yml +29 -0
- data/cider-ci/task_components/ruby.yml +15 -0
- data/friday.yml +3 -0
- data/lhc.gemspec +39 -0
- data/lib/core_ext/hash/deep_transform_values.rb +48 -0
- data/lib/lhc.rb +136 -0
- data/lib/lhc/concerns/lhc/basic_methods_concern.rb +42 -0
- data/lib/lhc/concerns/lhc/configuration_concern.rb +20 -0
- data/lib/lhc/concerns/lhc/fix_invalid_encoding_concern.rb +42 -0
- data/lib/lhc/concerns/lhc/formats_concern.rb +25 -0
- data/lib/lhc/concerns/lhc/request/user_agent_concern.rb +25 -0
- data/lib/lhc/config.rb +47 -0
- data/lib/lhc/endpoint.rb +119 -0
- data/lib/lhc/error.rb +80 -0
- data/lib/lhc/errors/client_error.rb +73 -0
- data/lib/lhc/errors/parser_error.rb +4 -0
- data/lib/lhc/errors/server_error.rb +28 -0
- data/lib/lhc/errors/timeout.rb +4 -0
- data/lib/lhc/errors/unknown_error.rb +4 -0
- data/lib/lhc/format.rb +18 -0
- data/lib/lhc/formats.rb +8 -0
- data/lib/lhc/formats/form.rb +45 -0
- data/lib/lhc/formats/json.rb +55 -0
- data/lib/lhc/formats/multipart.rb +45 -0
- data/lib/lhc/formats/plain.rb +42 -0
- data/lib/lhc/interceptor.rb +32 -0
- data/lib/lhc/interceptors.rb +26 -0
- data/lib/lhc/interceptors/auth.rb +98 -0
- data/lib/lhc/interceptors/caching.rb +127 -0
- data/lib/lhc/interceptors/default_timeout.rb +16 -0
- data/lib/lhc/interceptors/logging.rb +37 -0
- data/lib/lhc/interceptors/monitoring.rb +63 -0
- data/lib/lhc/interceptors/prometheus.rb +51 -0
- data/lib/lhc/interceptors/retry.rb +41 -0
- data/lib/lhc/interceptors/rollbar.rb +36 -0
- data/lib/lhc/interceptors/throttle.rb +81 -0
- data/lib/lhc/interceptors/zipkin.rb +110 -0
- data/lib/lhc/railtie.rb +10 -0
- data/lib/lhc/request.rb +157 -0
- data/lib/lhc/response.rb +60 -0
- data/lib/lhc/response/data.rb +28 -0
- data/lib/lhc/response/data/base.rb +22 -0
- data/lib/lhc/response/data/collection.rb +16 -0
- data/lib/lhc/response/data/item.rb +29 -0
- data/lib/lhc/rspec.rb +12 -0
- data/lib/lhc/test/cache_helper.rb +3 -0
- data/lib/lhc/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 +80 -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/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/options_spec.rb +89 -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 +29 -0
- data/spec/interceptors/dup_spec.rb +19 -0
- data/spec/interceptors/logging/main_spec.rb +37 -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 +41 -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 +106 -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 +37 -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 +61 -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 +8 -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 +7 -0
- data/spec/support/zipkin_mock.rb +113 -0
- data/spec/timeouts/no_signal_spec.rb +13 -0
- data/spec/timeouts/timings_spec.rb +55 -0
- metadata +534 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC do
|
|
6
|
+
include ActionDispatch::TestProcess
|
|
7
|
+
|
|
8
|
+
context 'multipart' do
|
|
9
|
+
let(:file) { fixture_file_upload(Tempfile.new, 'image/jpeg') }
|
|
10
|
+
let(:body) { { size: 2231 }.to_json }
|
|
11
|
+
let(:location) { 'http://local.ch/uploads/image.jpg' }
|
|
12
|
+
|
|
13
|
+
it 'formats requests to be multipart/form-data' do
|
|
14
|
+
stub_request(:post, 'http://local.ch/') do |request|
|
|
15
|
+
raise 'Content-Type header wrong' unless request.headers['Content-Type'] == 'multipart/form-data'
|
|
16
|
+
raise 'Body wrongly formatted' unless request.body.match(/file=%23%3CActionDispatch%3A%3AHttp%3A%3AUploadedFile%3A.*%3E&type=Image/)
|
|
17
|
+
end.to_return(status: 200, body: body, headers: { 'Location' => location })
|
|
18
|
+
response = LHC.multipart.post(
|
|
19
|
+
'http://local.ch',
|
|
20
|
+
body: { file: file, type: 'Image' }
|
|
21
|
+
)
|
|
22
|
+
expect(response.body).to eq body
|
|
23
|
+
expect(response.headers['Location']).to eq location
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC do
|
|
6
|
+
include ActionDispatch::TestProcess
|
|
7
|
+
|
|
8
|
+
context 'plain' do
|
|
9
|
+
let(:file) { fixture_file_upload(Tempfile.new, 'image/jpeg') }
|
|
10
|
+
|
|
11
|
+
it 'leaves plains requests unformatted' do
|
|
12
|
+
stub_request(:post, 'http://local.ch/')
|
|
13
|
+
.with(body: /file=%23%3CRack%3A%3ATest%3A%3AUploadedFile%3.*%3E&type=Image/)
|
|
14
|
+
.to_return do |request|
|
|
15
|
+
expect(request.headers['Content-Type']).to be_blank
|
|
16
|
+
|
|
17
|
+
{ status: 204 }
|
|
18
|
+
end
|
|
19
|
+
response = LHC.plain.post(
|
|
20
|
+
'http://local.ch',
|
|
21
|
+
body: { file: file, type: 'Image' }
|
|
22
|
+
)
|
|
23
|
+
expect(lambda {
|
|
24
|
+
response.body
|
|
25
|
+
response.data
|
|
26
|
+
}).not_to raise_error
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC do
|
|
6
|
+
context 'interceptor' do
|
|
7
|
+
before(:each) do
|
|
8
|
+
class SomeInterceptor < LHC::Interceptor
|
|
9
|
+
def after_request; end
|
|
10
|
+
end
|
|
11
|
+
LHC.configure { |c| c.interceptors = [SomeInterceptor] }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'can perform some actions after a request was fired' do
|
|
15
|
+
expect_any_instance_of(SomeInterceptor).to receive(:after_request)
|
|
16
|
+
stub_request(:get, 'http://local.ch')
|
|
17
|
+
LHC.get('http://local.ch')
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC 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 < LHC::Interceptor
|
|
13
|
+
def after_response
|
|
14
|
+
uri = URI.parse(response.request.url)
|
|
15
|
+
path = [
|
|
16
|
+
'web',
|
|
17
|
+
Rails.application.class.parent_name,
|
|
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
|
+
LHC.configure { |c| c.interceptors = [StatsTimingInterceptor] }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
let(:url) { "http://local.ch/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.local.ch.200', 0)
|
|
34
|
+
stub_request(:get, url)
|
|
35
|
+
LHC.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 LHC::Auth do
|
|
6
|
+
before(:each) do
|
|
7
|
+
LHC.config.interceptors = [LHC::Auth]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'adds basic auth to every request' do
|
|
11
|
+
options = { basic: { username: 'steve', password: 'can' } }
|
|
12
|
+
LHC.config.endpoint(:local, 'http://local.ch', auth: options)
|
|
13
|
+
stub_request(:get, 'http://local.ch')
|
|
14
|
+
.with(headers: { 'Authorization' => 'Basic c3RldmU6Y2Fu' })
|
|
15
|
+
LHC.get(:local)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC::Auth do
|
|
6
|
+
before(:each) do
|
|
7
|
+
LHC.config.interceptors = [LHC::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
|
+
LHC.config.endpoint(:local, 'http://local.ch', auth: options)
|
|
16
|
+
stub_request(:get, 'http://local.ch').with(headers: { 'Authorization' => 'Bearer 123456' })
|
|
17
|
+
LHC.get(:local)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC::Auth do
|
|
6
|
+
let(:bearer_token) { '123456' }
|
|
7
|
+
|
|
8
|
+
before(:each) do
|
|
9
|
+
stub_request(:get, 'http://local.ch').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) { LHC.config.interceptors = [LHC::Auth, LHC::Retry] }
|
|
16
|
+
|
|
17
|
+
it "max_recovery_attempts is zero" do
|
|
18
|
+
expect_any_instance_of(described_class).not_to receive(:warn)
|
|
19
|
+
LHC.config.endpoint(:local, 'http://local.ch', auth: options.merge(max_recovery_attempts: 0))
|
|
20
|
+
LHC.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
|
+
LHC.config.endpoint(:local, 'http://local.ch', auth: options)
|
|
26
|
+
LHC.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
|
+
LHC.config.interceptors = [LHC::Auth, LHC::Retry]
|
|
35
|
+
LHC.config.endpoint(:local, 'http://local.ch', auth: options)
|
|
36
|
+
expect_any_instance_of(described_class).not_to receive(:warn)
|
|
37
|
+
LHC.get(:local)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "warn refresh_client_token is a string" do
|
|
41
|
+
LHC.config.interceptors = [LHC::Auth, LHC::Retry]
|
|
42
|
+
LHC.config.endpoint(:local, 'http://local.ch', 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
|
+
LHC.get(:local)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "warn interceptors miss LHC::Retry" do
|
|
48
|
+
LHC.config.interceptors = [LHC::Auth]
|
|
49
|
+
LHC.config.endpoint(:local, 'http://local.ch', auth: options)
|
|
50
|
+
expect_any_instance_of(described_class).to receive(:warn).with("[WARNING] Your interceptors must include LHC::Retry after LHC::Auth.")
|
|
51
|
+
LHC.get(:local)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "warn interceptors LHC::Retry before LHC::Auth" do
|
|
55
|
+
LHC.config.interceptors = [LHC::Retry, LHC::Auth]
|
|
56
|
+
LHC.config.endpoint(:local, 'http://local.ch', auth: options)
|
|
57
|
+
expect_any_instance_of(described_class).to receive(:warn).with("[WARNING] Your interceptors must include LHC::Retry after LHC::Auth.")
|
|
58
|
+
LHC.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 LHC::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://local.ch')
|
|
11
|
+
.with(headers: { 'Authorization' => "Bearer #{initial_token}" })
|
|
12
|
+
.to_return(status: 401, body: "{}") # LHC::Unauthorized
|
|
13
|
+
end
|
|
14
|
+
let!(:auth_suceeding_after_recovery) do
|
|
15
|
+
stub_request(:get, 'http://local.ch')
|
|
16
|
+
.with(headers: { 'Authorization' => "Bearer #{refresh_token}" })
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
before(:each) do
|
|
20
|
+
LHC.config.interceptors = [LHC::Auth, LHC::Retry]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "recovery is attempted" do
|
|
24
|
+
LHC.config.endpoint(:local, 'http://local.ch', auth: options)
|
|
25
|
+
# the retried request (with updated Bearer), that should work
|
|
26
|
+
LHC.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
|
+
LHC.config.endpoint(:local, 'http://local.ch', auth: options.merge(reauthenticated: true))
|
|
32
|
+
expect { LHC.get(:local) }.to raise_error(LHC::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
|
+
LHC.config.endpoint(:local, 'http://local.ch', auth: options)
|
|
40
|
+
LHC.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 LHC do
|
|
6
|
+
context 'interceptor' do
|
|
7
|
+
before(:each) do
|
|
8
|
+
class TrackingIdInterceptor < LHC::Interceptor
|
|
9
|
+
def before_request
|
|
10
|
+
request.params[:tid] = 123
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
LHC.configure { |c| c.interceptors = [TrackingIdInterceptor] }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'can modify requests before they are send' do
|
|
17
|
+
stub_request(:get, "http://local.ch/?tid=123")
|
|
18
|
+
LHC.get('http://local.ch')
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC do
|
|
6
|
+
context 'interceptor' do
|
|
7
|
+
before(:each) do
|
|
8
|
+
class SomeInterceptor < LHC::Interceptor
|
|
9
|
+
def before_response; end
|
|
10
|
+
end
|
|
11
|
+
LHC.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://local.ch')
|
|
17
|
+
LHC.get('http://local.ch')
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC::Caching do
|
|
6
|
+
before(:each) do
|
|
7
|
+
LHC.config.interceptors = [LHC::Caching]
|
|
8
|
+
LHC::Caching.cache = Rails.cache
|
|
9
|
+
Rails.cache.clear
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let!(:first_request) do
|
|
13
|
+
stub_request(:get, "http://local.ch/").to_return(body: 'Website')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
let!(:second_request) do
|
|
17
|
+
stub_request(:get, "http://local.ch/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
|
+
LHC.request([{ url: 'http://local.ch', cache: true }, { url: 'http://local.ch/weather', cache: true }])
|
|
22
|
+
LHC.request([{ url: 'http://local.ch', cache: true }, { url: 'http://local.ch/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 LHC::Caching do
|
|
6
|
+
before(:each) do
|
|
7
|
+
LHC.config.interceptors = [LHC::Caching]
|
|
8
|
+
LHC::Caching.cache = Rails.cache
|
|
9
|
+
Rails.cache.clear
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let(:stub) { stub_request(:get, 'http://local.ch').to_return(status: 200, body: 'The Website') }
|
|
13
|
+
|
|
14
|
+
it 'serves a response from cache' do
|
|
15
|
+
stub
|
|
16
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: { expires_in: 5.minutes })
|
|
17
|
+
expect(Rails.cache).to receive(:write)
|
|
18
|
+
.with(
|
|
19
|
+
"LHC_CACHE(v#{LHC::Caching::CACHE_VERSION}): GET http://local.ch",
|
|
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 = LHC.get(:local)
|
|
30
|
+
cached_response = LHC.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
|
+
LHC.config.endpoint(:local, 'http://local.ch')
|
|
41
|
+
expect(Rails.cache).not_to receive(:write)
|
|
42
|
+
expect(Rails.cache).not_to receive(:fetch)
|
|
43
|
+
stub
|
|
44
|
+
2.times { LHC.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
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: { key: 'STATICKEY' })
|
|
50
|
+
expect(Rails.cache).to receive(:fetch).with("LHC_CACHE(v#{LHC::Caching::CACHE_VERSION}): STATICKEY").and_call_original
|
|
51
|
+
expect(Rails.cache).to receive(:write).with("LHC_CACHE(v#{LHC::Caching::CACHE_VERSION}): STATICKEY", anything, anything).and_call_original
|
|
52
|
+
stub
|
|
53
|
+
LHC.get(:local)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'does not store server errors in cache' do
|
|
57
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: true)
|
|
58
|
+
stub_request(:get, 'http://local.ch').to_return(status: 500, body: 'ERROR')
|
|
59
|
+
expect { LHC.get(:local) }.to raise_error LHC::ServerError
|
|
60
|
+
stub
|
|
61
|
+
expect(Rails.cache).to receive(:write).once
|
|
62
|
+
LHC.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
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: true)
|
|
68
|
+
original_response = LHC.get(:local)
|
|
69
|
+
cached_response = LHC.get(:local)
|
|
70
|
+
expect(original_response.from_cache?).to eq false
|
|
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 LHC::Caching do
|
|
6
|
+
before(:each) do
|
|
7
|
+
LHC.config.interceptors = [LHC::Caching]
|
|
8
|
+
LHC::Caching.cache = Rails.cache
|
|
9
|
+
Rails.cache.clear
|
|
10
|
+
|
|
11
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: { expires_in: 5.minutes })
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
let!(:stub) { stub_request(:post, 'http://local.ch').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
|
+
LHC.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
|
+
"LHC_CACHE(v#{LHC::Caching::CACHE_VERSION}): POST http://local.ch",
|
|
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 = LHC.post(:local, cache: { methods: [:post] })
|
|
36
|
+
cached_response = LHC.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
|