lhc 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/Gemfile +11 -0
  4. data/README.md +116 -0
  5. data/Rakefile +25 -0
  6. data/docs/configuration.md +57 -0
  7. data/docs/exceptions.md +68 -0
  8. data/docs/interceptors.md +90 -0
  9. data/docs/request.md +24 -0
  10. data/docs/response.md +19 -0
  11. data/lhc.gemspec +30 -0
  12. data/lib/lhc.rb +16 -0
  13. data/lib/lhc/concerns/lhc/basic_methods.rb +42 -0
  14. data/lib/lhc/config.rb +45 -0
  15. data/lib/lhc/endpoint.rb +53 -0
  16. data/lib/lhc/error.rb +63 -0
  17. data/lib/lhc/errors/client_error.rb +73 -0
  18. data/lib/lhc/errors/server_error.rb +28 -0
  19. data/lib/lhc/errors/timeout.rb +4 -0
  20. data/lib/lhc/errors/unknown_error.rb +4 -0
  21. data/lib/lhc/interceptor.rb +9 -0
  22. data/lib/lhc/interceptor_processor.rb +24 -0
  23. data/lib/lhc/request.rb +91 -0
  24. data/lib/lhc/response.rb +52 -0
  25. data/lib/lhc/version.rb +3 -0
  26. data/script/ci/build.sh +19 -0
  27. data/spec/basic_methods/delete_spec.rb +34 -0
  28. data/spec/basic_methods/get_spec.rb +37 -0
  29. data/spec/basic_methods/post_spec.rb +42 -0
  30. data/spec/basic_methods/put_spec.rb +48 -0
  31. data/spec/basic_methods/request_spec.rb +19 -0
  32. data/spec/config/endpoints_spec.rb +49 -0
  33. data/spec/config/placeholders_spec.rb +32 -0
  34. data/spec/dummy/README.rdoc +28 -0
  35. data/spec/dummy/Rakefile +6 -0
  36. data/spec/dummy/app/assets/images/.keep +0 -0
  37. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  38. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  39. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  40. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  41. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  42. data/spec/dummy/app/mailers/.keep +0 -0
  43. data/spec/dummy/app/models/.keep +0 -0
  44. data/spec/dummy/app/models/concerns/.keep +0 -0
  45. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  46. data/spec/dummy/bin/bundle +3 -0
  47. data/spec/dummy/bin/rails +4 -0
  48. data/spec/dummy/bin/rake +4 -0
  49. data/spec/dummy/config.ru +4 -0
  50. data/spec/dummy/config/application.rb +14 -0
  51. data/spec/dummy/config/boot.rb +5 -0
  52. data/spec/dummy/config/environment.rb +5 -0
  53. data/spec/dummy/config/environments/development.rb +34 -0
  54. data/spec/dummy/config/environments/production.rb +75 -0
  55. data/spec/dummy/config/environments/test.rb +39 -0
  56. data/spec/dummy/config/initializers/assets.rb +8 -0
  57. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  58. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  59. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  60. data/spec/dummy/config/initializers/inflections.rb +16 -0
  61. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  62. data/spec/dummy/config/initializers/session_store.rb +3 -0
  63. data/spec/dummy/config/initializers/wrap_parameters.rb +9 -0
  64. data/spec/dummy/config/locales/en.yml +23 -0
  65. data/spec/dummy/config/routes.rb +56 -0
  66. data/spec/dummy/config/secrets.yml +22 -0
  67. data/spec/dummy/lib/assets/.keep +0 -0
  68. data/spec/dummy/log/.keep +0 -0
  69. data/spec/dummy/public/404.html +67 -0
  70. data/spec/dummy/public/422.html +67 -0
  71. data/spec/dummy/public/500.html +66 -0
  72. data/spec/dummy/public/favicon.ico +0 -0
  73. data/spec/endpoint/compile_spec.rb +25 -0
  74. data/spec/endpoint/placeholders_spec.rb +14 -0
  75. data/spec/endpoint/remove_interpolated_params_spec.rb +16 -0
  76. data/spec/error/find_spec.rb +56 -0
  77. data/spec/error/response_spec.rb +17 -0
  78. data/spec/error/timeout_spec.rb +14 -0
  79. data/spec/interceptors/after_request_spec.rb +21 -0
  80. data/spec/interceptors/after_response_spec.rb +42 -0
  81. data/spec/interceptors/before_request_spec.rb +21 -0
  82. data/spec/interceptors/before_response_spec.rb +21 -0
  83. data/spec/interceptors/default_interceptors_spec.rb +15 -0
  84. data/spec/interceptors/define_spec.rb +29 -0
  85. data/spec/interceptors/response_competition_spec.rb +40 -0
  86. data/spec/interceptors/return_response_spec.rb +39 -0
  87. data/spec/rails_helper.rb +4 -0
  88. data/spec/request/error_handling_spec.rb +52 -0
  89. data/spec/request/headers_spec.rb +11 -0
  90. data/spec/request/option_dup_spec.rb +12 -0
  91. data/spec/request/parallel_requests_spec.rb +15 -0
  92. data/spec/request/url_patterns_spec.rb +19 -0
  93. data/spec/response/body_spec.rb +16 -0
  94. data/spec/response/code_spec.rb +16 -0
  95. data/spec/response/data_spec.rb +18 -0
  96. data/spec/response/headers_spec.rb +18 -0
  97. data/spec/response/success_spec.rb +12 -0
  98. data/spec/response/time_spec.rb +16 -0
  99. data/spec/spec_helper.rb +4 -0
  100. data/spec/support/fixtures/json/feedback.json +11 -0
  101. data/spec/support/fixtures/json/feedbacks.json +164 -0
  102. data/spec/support/fixtures/json/localina_content_ad.json +23 -0
  103. data/spec/support/load_json.rb +3 -0
  104. data/spec/support/reset_config.rb +7 -0
  105. data/spec/timeouts/no_signal_spec.rb +13 -0
  106. data/spec/timeouts/timings_spec.rb +59 -0
  107. metadata +313 -0
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/422.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The change you wanted was rejected.</h1>
62
+ <p>Maybe you tried to change something you didn't have access to.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/500.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>We're sorry, but something went wrong.</h1>
62
+ </div>
63
+ <p>If you are the application owner check the logs for more information.</p>
64
+ </div>
65
+ </body>
66
+ </html>
File without changes
@@ -0,0 +1,25 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Endpoint do
4
+
5
+ context 'compile' do
6
+
7
+ it 'uses parameters for interpolation' do
8
+ endpoint = LHC::Endpoint.new(':datastore/v2/:campaign_id/feedbacks')
9
+ expect(
10
+ endpoint.compile(datastore: 'http://datastore.lb-service', campaign_id: 'abc')
11
+ ).to eq "http://datastore.lb-service/v2/abc/feedbacks"
12
+ end
13
+
14
+ it 'uses provided proc to find values' do
15
+ endpoint = LHC::Endpoint.new(':datastore/v2')
16
+ config = { datastore: 'http://datastore.lb-service' }
17
+ find_value = ->(match){
18
+ config[match.gsub(':', '').to_sym]
19
+ }
20
+ expect(
21
+ endpoint.compile(find_value)
22
+ ).to eq "http://datastore.lb-service/v2"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Endpoint do
4
+
5
+ context 'placeholders' do
6
+
7
+ it 'returns all placeholders alphabetically sorted' do
8
+ endpoint = LHC::Endpoint.new(':datastore/v2/:campaign_id/feedbacks')
9
+ expect(
10
+ endpoint.placeholders
11
+ ).to eq [':campaign_id', ':datastore']
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Endpoint do
4
+
5
+ it 'removes params used for interpolation' do
6
+ params = {
7
+ datastore: 'http://datastore.lb-service',
8
+ campaign_id: 'abc',
9
+ has_reviews: true
10
+ }
11
+ endpoint = LHC::Endpoint.new(':datastore/v2/:campaign_id/feedbacks')
12
+ removed = endpoint.remove_interpolated_params!(params)
13
+ expect(params).to eq ({ has_reviews: true })
14
+ expect(removed).to eq(datastore: 'http://datastore.lb-service', campaign_id: 'abc')
15
+ end
16
+ end
@@ -0,0 +1,56 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Error do
4
+
5
+ def response(code)
6
+ LHC::Response.new(OpenStruct.new({code: code}), nil)
7
+ end
8
+
9
+ context 'find' do
10
+
11
+ it 'finds error class by status code' do
12
+ expect(LHC::Error.find(response('400'))).to eq LHC::BadRequest
13
+ expect(LHC::Error.find(response('401'))).to eq LHC::Unauthorized
14
+ expect(LHC::Error.find(response('402'))).to eq LHC::PaymentRequired
15
+ expect(LHC::Error.find(response('403'))).to eq LHC::Forbidden
16
+ expect(LHC::Error.find(response('403'))).to eq LHC::Forbidden
17
+ expect(LHC::Error.find(response('404'))).to eq LHC::NotFound
18
+ expect(LHC::Error.find(response('405'))).to eq LHC::MethodNotAllowed
19
+ expect(LHC::Error.find(response('406'))).to eq LHC::NotAcceptable
20
+ expect(LHC::Error.find(response('407'))).to eq LHC::ProxyAuthenticationRequired
21
+ expect(LHC::Error.find(response('408'))).to eq LHC::RequestTimeout
22
+ expect(LHC::Error.find(response('409'))).to eq LHC::Conflict
23
+ expect(LHC::Error.find(response('410'))).to eq LHC::Gone
24
+ expect(LHC::Error.find(response('411'))).to eq LHC::LengthRequired
25
+ expect(LHC::Error.find(response('412'))).to eq LHC::PreconditionFailed
26
+ expect(LHC::Error.find(response('413'))).to eq LHC::RequestEntityTooLarge
27
+ expect(LHC::Error.find(response('414'))).to eq LHC::RequestUriToLong
28
+ expect(LHC::Error.find(response('415'))).to eq LHC::UnsupportedMediaType
29
+ expect(LHC::Error.find(response('416'))).to eq LHC::RequestedRangeNotSatisfiable
30
+ expect(LHC::Error.find(response('417'))).to eq LHC::ExpectationFailed
31
+ expect(LHC::Error.find(response('422'))).to eq LHC::UnprocessableEntity
32
+ expect(LHC::Error.find(response('423'))).to eq LHC::Locked
33
+ expect(LHC::Error.find(response('424'))).to eq LHC::FailedDependency
34
+ expect(LHC::Error.find(response('426'))).to eq LHC::UpgradeRequired
35
+ expect(LHC::Error.find(response('500'))).to eq LHC::InternalServerError
36
+ expect(LHC::Error.find(response('501'))).to eq LHC::NotImplemented
37
+ expect(LHC::Error.find(response('502'))).to eq LHC::BadGateway
38
+ expect(LHC::Error.find(response('503'))).to eq LHC::ServiceUnavailable
39
+ expect(LHC::Error.find(response('504'))).to eq LHC::GatewayTimeout
40
+ expect(LHC::Error.find(response('505'))).to eq LHC::HttpVersionNotSupported
41
+ expect(LHC::Error.find(response('507'))).to eq LHC::InsufficientStorage
42
+ expect(LHC::Error.find(response('510'))).to eq LHC::NotExtended
43
+ end
44
+
45
+ it 'finds error class also by extended status codes' do
46
+ expect(LHC::Error.find(response('40001'))).to eq LHC::BadRequest
47
+ expect(LHC::Error.find(response('50002'))).to eq LHC::InternalServerError
48
+ end
49
+
50
+ it 'returns UnknownError if no specific error was found' do
51
+ expect(LHC::Error.find(response('0'))).to eq LHC::UnknownError
52
+ expect(LHC::Error.find(response(''))).to eq LHC::UnknownError
53
+ expect(LHC::Error.find(response('600'))).to eq LHC::UnknownError
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,17 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Error do
4
+
5
+ context 'response' do
6
+
7
+ it 'throws timeout exception in case of a timeout' do
8
+ stub_request(:any, 'local.ch').to_return(status: 403)
9
+ begin
10
+ LHC.get('local.ch')
11
+ rescue => e
12
+ expect(e.response).to be_kind_of(LHC::Response)
13
+ expect(e.response.code).to eq 403
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC::Error do
4
+
5
+ context 'timeout' do
6
+
7
+ it 'throws timeout exception in case of a timeout' do
8
+ stub_request(:any, 'local.ch').to_timeout
9
+ expect(->{
10
+ LHC.get('local.ch')
11
+ }).to raise_error LHC::Timeout
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC do
4
+
5
+ context 'interceptor' do
6
+
7
+ before(:each) do
8
+ class SomeInterceptor < LHC::Interceptor
9
+ def after_request(request)
10
+ end
11
+ end
12
+ LHC.configure { |c| c.interceptors = [SomeInterceptor] }
13
+ end
14
+
15
+ it 'can perform some actions after a request was fired' do
16
+ expect_any_instance_of(SomeInterceptor).to receive(:after_request)
17
+ stub_request(:get, 'http://local.ch')
18
+ LHC.get('http://local.ch')
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,42 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC do
4
+
5
+ context 'interceptor' do
6
+
7
+ before(:each) do
8
+ class Services
9
+ def self.timing(path, time)
10
+ end
11
+ end
12
+ end
13
+
14
+ before(:each) do
15
+ class StatsTimingInterceptor < LHC::Interceptor
16
+ def after_response(response)
17
+ uri = URI.parse(response.request.url)
18
+ path = [
19
+ 'web',
20
+ Rails.application.class.parent_name,
21
+ Rails.env,
22
+ response.request.method,
23
+ uri.scheme,
24
+ uri.host,
25
+ response.code
26
+ ].join('.')
27
+ Services.timing(path.downcase, response.time)
28
+ end
29
+ end
30
+ LHC.configure { |c| c.interceptors = [StatsTimingInterceptor] }
31
+ end
32
+
33
+ let(:url) { "http://datastore-stg.lb-service.sunrise.intra.local.ch/v2/feedbacks/-Sc4_pYNpqfsudzhtivfkA" }
34
+
35
+ it 'can take action after a response was received' do
36
+ allow(Services).to receive(:timing).with('web.dummy.test.get.http.datastore-stg.lb-service.sunrise.intra.local.ch.200', 0)
37
+ stub_request(:get, url)
38
+ LHC.get(url)
39
+ expect(Services).to have_received(:timing)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,21 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC do
4
+
5
+ context 'interceptor' do
6
+
7
+ before(:each) do
8
+ class TrackingIdInterceptor < LHC::Interceptor
9
+ def before_request(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,21 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC do
4
+
5
+ context 'interceptor' do
6
+
7
+ before(:each) do
8
+ class SomeInterceptor < LHC::Interceptor
9
+ def before_response(request)
10
+ end
11
+ end
12
+ LHC.configure { |c| c.interceptors = [SomeInterceptor] }
13
+ end
14
+
15
+ it 'can perform some actions before a reponse is received' do
16
+ expect_any_instance_of(SomeInterceptor).to receive(:before_response)
17
+ stub_request(:get, 'http://local.ch')
18
+ LHC.get('http://local.ch')
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC do
4
+
5
+ context 'default interceptors' do
6
+
7
+ before(:each) do
8
+ LHC.configure {}
9
+ end
10
+
11
+ it 'should always return a list for default interceptors' do
12
+ expect(LHC.config.interceptors).to eq []
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,29 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHC do
4
+
5
+ context 'interceptor' do
6
+
7
+ before(:each) do
8
+ class SomeInterceptor < LHC::Interceptor
9
+ end
10
+ class AnotherInterceptor < LHC::Interceptor
11
+ end
12
+ end
13
+
14
+ it 'performs interceptor when they are set globally' do
15
+ LHC.configure { |c| c.interceptors = [SomeInterceptor] }
16
+ expect_any_instance_of(SomeInterceptor).to receive(:before_request)
17
+ stub_request(:get, 'http://local.ch')
18
+ LHC.get('http://local.ch')
19
+ end
20
+
21
+ it 'overrides interceptors on request level' do
22
+ LHC.configure { |c| c.interceptors = [SomeInterceptor] }
23
+ expect_any_instance_of(AnotherInterceptor).to receive(:before_request)
24
+ expect_any_instance_of(SomeInterceptor).not_to receive(:before_request)
25
+ stub_request(:get, 'http://local.ch')
26
+ LHC.get('http://local.ch', interceptors: [AnotherInterceptor])
27
+ end
28
+ end
29
+ end