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.
Files changed (195) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +37 -0
  3. data/.rubocop.localch.yml +325 -0
  4. data/.rubocop.yml +61 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +13 -0
  7. data/Gemfile.activesupport4 +4 -0
  8. data/Gemfile.activesupport5 +4 -0
  9. data/Gemfile.activesupport6 +4 -0
  10. data/LICENSE +674 -0
  11. data/README.md +984 -0
  12. data/Rakefile +25 -0
  13. data/cider-ci.yml +6 -0
  14. data/cider-ci/bin/bundle +51 -0
  15. data/cider-ci/bin/ruby_install +8 -0
  16. data/cider-ci/bin/ruby_version +25 -0
  17. data/cider-ci/jobs/rspec-activesupport-4.yml +28 -0
  18. data/cider-ci/jobs/rspec-activesupport-5.yml +27 -0
  19. data/cider-ci/jobs/rspec-activesupport-6.yml +28 -0
  20. data/cider-ci/jobs/rubocop.yml +18 -0
  21. data/cider-ci/task_components/bundle.yml +22 -0
  22. data/cider-ci/task_components/rspec.yml +36 -0
  23. data/cider-ci/task_components/rubocop.yml +29 -0
  24. data/cider-ci/task_components/ruby.yml +15 -0
  25. data/friday.yml +3 -0
  26. data/lhc.gemspec +39 -0
  27. data/lib/core_ext/hash/deep_transform_values.rb +48 -0
  28. data/lib/lhc.rb +136 -0
  29. data/lib/lhc/concerns/lhc/basic_methods_concern.rb +42 -0
  30. data/lib/lhc/concerns/lhc/configuration_concern.rb +20 -0
  31. data/lib/lhc/concerns/lhc/fix_invalid_encoding_concern.rb +42 -0
  32. data/lib/lhc/concerns/lhc/formats_concern.rb +25 -0
  33. data/lib/lhc/concerns/lhc/request/user_agent_concern.rb +25 -0
  34. data/lib/lhc/config.rb +47 -0
  35. data/lib/lhc/endpoint.rb +119 -0
  36. data/lib/lhc/error.rb +80 -0
  37. data/lib/lhc/errors/client_error.rb +73 -0
  38. data/lib/lhc/errors/parser_error.rb +4 -0
  39. data/lib/lhc/errors/server_error.rb +28 -0
  40. data/lib/lhc/errors/timeout.rb +4 -0
  41. data/lib/lhc/errors/unknown_error.rb +4 -0
  42. data/lib/lhc/format.rb +18 -0
  43. data/lib/lhc/formats.rb +8 -0
  44. data/lib/lhc/formats/form.rb +45 -0
  45. data/lib/lhc/formats/json.rb +55 -0
  46. data/lib/lhc/formats/multipart.rb +45 -0
  47. data/lib/lhc/formats/plain.rb +42 -0
  48. data/lib/lhc/interceptor.rb +32 -0
  49. data/lib/lhc/interceptors.rb +26 -0
  50. data/lib/lhc/interceptors/auth.rb +98 -0
  51. data/lib/lhc/interceptors/caching.rb +127 -0
  52. data/lib/lhc/interceptors/default_timeout.rb +16 -0
  53. data/lib/lhc/interceptors/logging.rb +37 -0
  54. data/lib/lhc/interceptors/monitoring.rb +63 -0
  55. data/lib/lhc/interceptors/prometheus.rb +51 -0
  56. data/lib/lhc/interceptors/retry.rb +41 -0
  57. data/lib/lhc/interceptors/rollbar.rb +36 -0
  58. data/lib/lhc/interceptors/throttle.rb +81 -0
  59. data/lib/lhc/interceptors/zipkin.rb +110 -0
  60. data/lib/lhc/railtie.rb +10 -0
  61. data/lib/lhc/request.rb +157 -0
  62. data/lib/lhc/response.rb +60 -0
  63. data/lib/lhc/response/data.rb +28 -0
  64. data/lib/lhc/response/data/base.rb +22 -0
  65. data/lib/lhc/response/data/collection.rb +16 -0
  66. data/lib/lhc/response/data/item.rb +29 -0
  67. data/lib/lhc/rspec.rb +12 -0
  68. data/lib/lhc/test/cache_helper.rb +3 -0
  69. data/lib/lhc/version.rb +5 -0
  70. data/script/ci/build.sh +19 -0
  71. data/spec/basic_methods/delete_spec.rb +34 -0
  72. data/spec/basic_methods/get_spec.rb +49 -0
  73. data/spec/basic_methods/post_spec.rb +42 -0
  74. data/spec/basic_methods/put_spec.rb +48 -0
  75. data/spec/basic_methods/request_spec.rb +19 -0
  76. data/spec/basic_methods/request_without_rails_spec.rb +29 -0
  77. data/spec/config/endpoints_spec.rb +63 -0
  78. data/spec/config/placeholders_spec.rb +32 -0
  79. data/spec/core_ext/hash/deep_transform_values_spec.rb +24 -0
  80. data/spec/dummy/README.rdoc +28 -0
  81. data/spec/dummy/Rakefile +8 -0
  82. data/spec/dummy/app/assets/config/manifest.js +3 -0
  83. data/spec/dummy/app/assets/images/.keep +0 -0
  84. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  85. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  86. data/spec/dummy/app/controllers/application_controller.rb +7 -0
  87. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  88. data/spec/dummy/app/helpers/application_helper.rb +4 -0
  89. data/spec/dummy/app/mailers/.keep +0 -0
  90. data/spec/dummy/app/models/.keep +0 -0
  91. data/spec/dummy/app/models/concerns/.keep +0 -0
  92. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  93. data/spec/dummy/bin/bundle +5 -0
  94. data/spec/dummy/bin/rails +6 -0
  95. data/spec/dummy/bin/rake +6 -0
  96. data/spec/dummy/config.ru +6 -0
  97. data/spec/dummy/config/application.rb +16 -0
  98. data/spec/dummy/config/boot.rb +7 -0
  99. data/spec/dummy/config/environment.rb +7 -0
  100. data/spec/dummy/config/environments/development.rb +36 -0
  101. data/spec/dummy/config/environments/production.rb +77 -0
  102. data/spec/dummy/config/environments/test.rb +41 -0
  103. data/spec/dummy/config/initializers/assets.rb +10 -0
  104. data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
  105. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  106. data/spec/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  107. data/spec/dummy/config/initializers/inflections.rb +18 -0
  108. data/spec/dummy/config/initializers/mime_types.rb +6 -0
  109. data/spec/dummy/config/initializers/session_store.rb +5 -0
  110. data/spec/dummy/config/initializers/wrap_parameters.rb +11 -0
  111. data/spec/dummy/config/locales/en.yml +23 -0
  112. data/spec/dummy/config/routes.rb +58 -0
  113. data/spec/dummy/config/secrets.yml +22 -0
  114. data/spec/dummy/lib/assets/.keep +0 -0
  115. data/spec/dummy/log/.keep +0 -0
  116. data/spec/dummy/public/404.html +67 -0
  117. data/spec/dummy/public/422.html +67 -0
  118. data/spec/dummy/public/500.html +66 -0
  119. data/spec/dummy/public/favicon.ico +0 -0
  120. data/spec/endpoint/compile_spec.rb +35 -0
  121. data/spec/endpoint/match_spec.rb +41 -0
  122. data/spec/endpoint/placeholders_spec.rb +30 -0
  123. data/spec/endpoint/remove_interpolated_params_spec.rb +17 -0
  124. data/spec/endpoint/values_as_params_spec.rb +31 -0
  125. data/spec/error/dup_spec.rb +12 -0
  126. data/spec/error/find_spec.rb +57 -0
  127. data/spec/error/response_spec.rb +17 -0
  128. data/spec/error/timeout_spec.rb +14 -0
  129. data/spec/error/to_s_spec.rb +80 -0
  130. data/spec/formats/form_spec.rb +27 -0
  131. data/spec/formats/json_spec.rb +66 -0
  132. data/spec/formats/multipart_spec.rb +26 -0
  133. data/spec/formats/plain_spec.rb +29 -0
  134. data/spec/interceptors/after_request_spec.rb +20 -0
  135. data/spec/interceptors/after_response_spec.rb +39 -0
  136. data/spec/interceptors/auth/basic_auth_spec.rb +17 -0
  137. data/spec/interceptors/auth/bearer_spec.rb +19 -0
  138. data/spec/interceptors/auth/reauthentication_configuration_spec.rb +61 -0
  139. data/spec/interceptors/auth/reauthentication_spec.rb +44 -0
  140. data/spec/interceptors/before_request_spec.rb +21 -0
  141. data/spec/interceptors/before_response_spec.rb +20 -0
  142. data/spec/interceptors/caching/hydra_spec.rb +26 -0
  143. data/spec/interceptors/caching/main_spec.rb +73 -0
  144. data/spec/interceptors/caching/methods_spec.rb +42 -0
  145. data/spec/interceptors/caching/options_spec.rb +89 -0
  146. data/spec/interceptors/caching/parameters_spec.rb +24 -0
  147. data/spec/interceptors/caching/response_status_spec.rb +29 -0
  148. data/spec/interceptors/caching/to_cache_spec.rb +16 -0
  149. data/spec/interceptors/default_interceptors_spec.rb +15 -0
  150. data/spec/interceptors/default_timeout/main_spec.rb +34 -0
  151. data/spec/interceptors/define_spec.rb +29 -0
  152. data/spec/interceptors/dup_spec.rb +19 -0
  153. data/spec/interceptors/logging/main_spec.rb +37 -0
  154. data/spec/interceptors/monitoring/main_spec.rb +97 -0
  155. data/spec/interceptors/prometheus_spec.rb +54 -0
  156. data/spec/interceptors/response_competition_spec.rb +41 -0
  157. data/spec/interceptors/retry/main_spec.rb +73 -0
  158. data/spec/interceptors/return_response_spec.rb +38 -0
  159. data/spec/interceptors/rollbar/invalid_encoding_spec.rb +43 -0
  160. data/spec/interceptors/rollbar/main_spec.rb +57 -0
  161. data/spec/interceptors/throttle/main_spec.rb +106 -0
  162. data/spec/interceptors/throttle/reset_track_spec.rb +53 -0
  163. data/spec/interceptors/zipkin/distributed_tracing_spec.rb +135 -0
  164. data/spec/rails_helper.rb +6 -0
  165. data/spec/request/body_spec.rb +39 -0
  166. data/spec/request/encoding_spec.rb +37 -0
  167. data/spec/request/error_handling_spec.rb +88 -0
  168. data/spec/request/headers_spec.rb +12 -0
  169. data/spec/request/ignore_errors_spec.rb +73 -0
  170. data/spec/request/option_dup_spec.rb +13 -0
  171. data/spec/request/parallel_requests_spec.rb +59 -0
  172. data/spec/request/params_encoding_spec.rb +26 -0
  173. data/spec/request/request_without_rails_spec.rb +15 -0
  174. data/spec/request/url_patterns_spec.rb +54 -0
  175. data/spec/request/user_agent_spec.rb +26 -0
  176. data/spec/request/user_agent_without_rails_spec.rb +27 -0
  177. data/spec/response/body_spec.rb +16 -0
  178. data/spec/response/code_spec.rb +16 -0
  179. data/spec/response/data_accessor_spec.rb +29 -0
  180. data/spec/response/data_spec.rb +61 -0
  181. data/spec/response/effective_url_spec.rb +16 -0
  182. data/spec/response/headers_spec.rb +18 -0
  183. data/spec/response/options_spec.rb +18 -0
  184. data/spec/response/success_spec.rb +13 -0
  185. data/spec/response/time_spec.rb +21 -0
  186. data/spec/spec_helper.rb +8 -0
  187. data/spec/support/fixtures/json/feedback.json +11 -0
  188. data/spec/support/fixtures/json/feedbacks.json +164 -0
  189. data/spec/support/fixtures/json/localina_content_ad.json +23 -0
  190. data/spec/support/load_json.rb +5 -0
  191. data/spec/support/reset_config.rb +7 -0
  192. data/spec/support/zipkin_mock.rb +113 -0
  193. data/spec/timeouts/no_signal_spec.rb +13 -0
  194. data/spec/timeouts/timings_spec.rb +55 -0
  195. 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