lhc 12.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,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,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe LHC::Endpoint do
|
6
|
+
context 'compile' do
|
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', campaign_id: 'abc')
|
11
|
+
).to eq "http://datastore/v2/abc/feedbacks"
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'compiles when templates contain dots' do
|
15
|
+
endpoint = LHC::Endpoint.new('{+datastore}/entries/{id}.json')
|
16
|
+
expect(
|
17
|
+
endpoint.compile(datastore: 'http://datastore', id: 123)
|
18
|
+
).to eq "http://datastore/entries/123.json"
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'compiles complex urls containing all sort of characters' do
|
22
|
+
endpoint = LHC::Endpoint.new('{+ads}/?adrawdata/3.0/1108.1/2844859/0/0/header=yes;cookie=no;adct=204;alias={region_id}{lang}{product_type}{product};key=cat={category_id}')
|
23
|
+
expect(
|
24
|
+
endpoint.compile(ads: 'http://ads', region_id: 291, lang: 'de', product_type: 'ABC', product: 'xyz', category_id: 312)
|
25
|
+
).to eq 'http://ads/?adrawdata/3.0/1108.1/2844859/0/0/header=yes;cookie=no;adct=204;alias=291deABCxyz;key=cat=312'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'compiles complex urls containing &' do
|
29
|
+
endpoint = LHC::Endpoint.new('http://{+weather_search_host}/forecast?format=json&period=hour&limit={limit}&areas={+zipcodes}&when={when}')
|
30
|
+
expect(
|
31
|
+
endpoint.compile(weather_search_host: 'weather', limit: 5, zipcodes: [8005, 8004].join(','), when: 'today')
|
32
|
+
).to eq 'http://weather/forecast?format=json&period=hour&limit=5&areas=8005,8004&when=today'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe LHC::Endpoint do
|
6
|
+
context 'match' do
|
7
|
+
context 'matching' do
|
8
|
+
{
|
9
|
+
'{+datastore}/v2/places' => 'http://local.ch:8082/v2/places',
|
10
|
+
'{+datastore}/v2/places/{id}' => 'http://local.ch:8082/v2/places/ZW9OJyrbt4OZE9ueu80w-A',
|
11
|
+
'{+datastore}/v2/places/{namespace}/{id}' => 'http://local.ch:8082/v2/places/switzerland/ZW9OJyrbt',
|
12
|
+
'{+datastore}/addresses/{id}' => 'http://local.ch/addresses/123',
|
13
|
+
'http://local.ch/addresses/{id}' => 'http://local.ch/addresses/123',
|
14
|
+
'{+datastore}/customers/{id}/addresses' => 'http://local.ch:80/server/rest/v1/customers/123/addresses',
|
15
|
+
'{+datastore}/entries/{id}.json' => 'http://local.ch/entries/123.json',
|
16
|
+
'{+datastore}/places/{place_id}/feedbacks' => 'http://local.ch/places/1/feedbacks?limit=10&offset=0',
|
17
|
+
'http://local.ch/places/1/feedbacks' => 'http://local.ch/places/1/feedbacks?lang=en',
|
18
|
+
'http://local.ch/places/1/feedbacks.json' => 'http://local.ch/places/1/feedbacks.json?lang=en'
|
19
|
+
}.each do |template, url|
|
20
|
+
it "#{url} matches #{template}" do
|
21
|
+
expect(LHC::Endpoint.match?(url, template)).to be(true)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'not matching' do
|
27
|
+
{
|
28
|
+
'{+datastore}/v2/places' => 'http://local.ch:8082/v2/places/ZW9OJyrbt4OZE9ueu80w-A',
|
29
|
+
'{+datastore}/{campaign_id}/feedbacks' => 'http://datastore.local.ch/feedbacks',
|
30
|
+
'{+datastore}/customers/{id}' => 'http://local.ch:80/server/rest/v1/customers/123/addresses',
|
31
|
+
'{+datastore}/entries/{id}' => 'http://local.ch/entries/123.json'
|
32
|
+
}.each do |template, url|
|
33
|
+
it "#{url} should not match #{template}" do
|
34
|
+
expect(
|
35
|
+
LHC::Endpoint.match?(url, template)
|
36
|
+
).to be(false)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe LHC::Endpoint do
|
6
|
+
context 'placeholders' do
|
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
|
+
|
14
|
+
it 'allows basic auth token in url, like used on github' do
|
15
|
+
stub_request(:get, "https://d123token:@api.github.com/search")
|
16
|
+
.to_return(body: {}.to_json)
|
17
|
+
expect(-> {
|
18
|
+
LHC.get("https://d123token:@api.github.com/search")
|
19
|
+
}).not_to raise_error
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'allows complete basic auth (username password) in url, like used for the gemserer' do
|
23
|
+
stub_request(:get, "https://name:password@gemserver.com")
|
24
|
+
.to_return(body: {}.to_json)
|
25
|
+
expect(-> {
|
26
|
+
LHC.get("https://name:password@gemserver.com")
|
27
|
+
}).not_to raise_error
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe LHC::Endpoint do
|
6
|
+
it 'removes params used for interpolation' do
|
7
|
+
params = {
|
8
|
+
datastore: 'http://datastore',
|
9
|
+
campaign_id: 'abc',
|
10
|
+
has_reviews: true
|
11
|
+
}
|
12
|
+
endpoint = LHC::Endpoint.new('{+datastore}/v2/{campaign_id}/feedbacks')
|
13
|
+
removed = endpoint.remove_interpolated_params!(params)
|
14
|
+
expect(params).to eq(has_reviews: true)
|
15
|
+
expect(removed).to eq(datastore: 'http://datastore', campaign_id: 'abc')
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe LHC::Endpoint do
|
6
|
+
context 'values_as_params' do
|
7
|
+
[
|
8
|
+
['{+datastore}/v2/places', 'http://local.ch:8082/v2/places', {
|
9
|
+
datastore: 'http://local.ch:8082'
|
10
|
+
}],
|
11
|
+
['{+datastore}/v2/places/{id}', 'http://local.ch:8082/v2/places/ZW9OJyrbt4OZE9ueu80w-A', {
|
12
|
+
datastore: 'http://local.ch:8082',
|
13
|
+
id: 'ZW9OJyrbt4OZE9ueu80w-A'
|
14
|
+
}],
|
15
|
+
['{+datastore}/v2/places/{namespace}/{id}', 'http://local.ch:8082/v2/places/switzerland/ZW9OJyrbt', {
|
16
|
+
datastore: 'http://local.ch:8082',
|
17
|
+
namespace: 'switzerland',
|
18
|
+
id: 'ZW9OJyrbt'
|
19
|
+
}]
|
20
|
+
].each do |example|
|
21
|
+
template = example[0]
|
22
|
+
url = example[1]
|
23
|
+
params = example[2]
|
24
|
+
|
25
|
+
it "for the template #{template} it extracts #{params.keys.join(', ')} from the url" do
|
26
|
+
extracted = LHC::Endpoint.values_as_params(template, url)
|
27
|
+
expect(extracted).to eq(params)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe LHC::Error do
|
6
|
+
def response(code, timedout = false)
|
7
|
+
LHC::Response.new(OpenStruct.new(code: code, 'timed_out?' => timedout), nil)
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'find' do
|
11
|
+
it 'finds error class by status code' do
|
12
|
+
expect(LHC::Error.find(response('0', true))).to eq LHC::Timeout
|
13
|
+
expect(LHC::Error.find(response('400'))).to eq LHC::BadRequest
|
14
|
+
expect(LHC::Error.find(response('401'))).to eq LHC::Unauthorized
|
15
|
+
expect(LHC::Error.find(response('402'))).to eq LHC::PaymentRequired
|
16
|
+
expect(LHC::Error.find(response('403'))).to eq LHC::Forbidden
|
17
|
+
expect(LHC::Error.find(response('403'))).to eq LHC::Forbidden
|
18
|
+
expect(LHC::Error.find(response('404'))).to eq LHC::NotFound
|
19
|
+
expect(LHC::Error.find(response('405'))).to eq LHC::MethodNotAllowed
|
20
|
+
expect(LHC::Error.find(response('406'))).to eq LHC::NotAcceptable
|
21
|
+
expect(LHC::Error.find(response('407'))).to eq LHC::ProxyAuthenticationRequired
|
22
|
+
expect(LHC::Error.find(response('408'))).to eq LHC::RequestTimeout
|
23
|
+
expect(LHC::Error.find(response('409'))).to eq LHC::Conflict
|
24
|
+
expect(LHC::Error.find(response('410'))).to eq LHC::Gone
|
25
|
+
expect(LHC::Error.find(response('411'))).to eq LHC::LengthRequired
|
26
|
+
expect(LHC::Error.find(response('412'))).to eq LHC::PreconditionFailed
|
27
|
+
expect(LHC::Error.find(response('413'))).to eq LHC::RequestEntityTooLarge
|
28
|
+
expect(LHC::Error.find(response('414'))).to eq LHC::RequestUriToLong
|
29
|
+
expect(LHC::Error.find(response('415'))).to eq LHC::UnsupportedMediaType
|
30
|
+
expect(LHC::Error.find(response('416'))).to eq LHC::RequestedRangeNotSatisfiable
|
31
|
+
expect(LHC::Error.find(response('417'))).to eq LHC::ExpectationFailed
|
32
|
+
expect(LHC::Error.find(response('422'))).to eq LHC::UnprocessableEntity
|
33
|
+
expect(LHC::Error.find(response('423'))).to eq LHC::Locked
|
34
|
+
expect(LHC::Error.find(response('424'))).to eq LHC::FailedDependency
|
35
|
+
expect(LHC::Error.find(response('426'))).to eq LHC::UpgradeRequired
|
36
|
+
expect(LHC::Error.find(response('500'))).to eq LHC::InternalServerError
|
37
|
+
expect(LHC::Error.find(response('501'))).to eq LHC::NotImplemented
|
38
|
+
expect(LHC::Error.find(response('502'))).to eq LHC::BadGateway
|
39
|
+
expect(LHC::Error.find(response('503'))).to eq LHC::ServiceUnavailable
|
40
|
+
expect(LHC::Error.find(response('504'))).to eq LHC::GatewayTimeout
|
41
|
+
expect(LHC::Error.find(response('505'))).to eq LHC::HttpVersionNotSupported
|
42
|
+
expect(LHC::Error.find(response('507'))).to eq LHC::InsufficientStorage
|
43
|
+
expect(LHC::Error.find(response('510'))).to eq LHC::NotExtended
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'finds error class also by extended status codes' do
|
47
|
+
expect(LHC::Error.find(response('40001'))).to eq LHC::BadRequest
|
48
|
+
expect(LHC::Error.find(response('50002'))).to eq LHC::InternalServerError
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'returns UnknownError if no specific error was found' do
|
52
|
+
expect(LHC::Error.find(response('0'))).to eq LHC::UnknownError
|
53
|
+
expect(LHC::Error.find(response(''))).to eq LHC::UnknownError
|
54
|
+
expect(LHC::Error.find(response('600'))).to eq LHC::UnknownError
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe LHC::Error do
|
6
|
+
context 'response' do
|
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
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe LHC::Error do
|
6
|
+
context 'timeout' do
|
7
|
+
it 'throws timeout exception in case of a timeout' do
|
8
|
+
stub_request(:any, 'local.ch').to_timeout
|
9
|
+
expect(lambda {
|
10
|
+
LHC.get('local.ch')
|
11
|
+
}).to raise_error LHC::Timeout
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe LHC::Error do
|
6
|
+
context 'to_s' do
|
7
|
+
let(:invalid) { (+"in\xc3lid").force_encoding('ASCII-8BIT') }
|
8
|
+
let(:valid) { "vælid" }
|
9
|
+
|
10
|
+
context 'check assumptions' do
|
11
|
+
it 'joining raises an error' do
|
12
|
+
expect { [valid, invalid].join }.to raise_error Encoding::CompatibilityError
|
13
|
+
end
|
14
|
+
it 'interpolation raises an error' do
|
15
|
+
expect { "#{valid} #{invalid}" }.to raise_error Encoding::CompatibilityError
|
16
|
+
end
|
17
|
+
it 'to_json on an array raises an error' do
|
18
|
+
expect { [valid, invalid].to_json }.to raise_error Encoding::UndefinedConversionError
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'to_s on a hash does not raise an error' do
|
22
|
+
expect { { valid: valid, invalid: invalid }.to_s }.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'to_json on a hash does raise an error' do
|
26
|
+
expect { { valid: valid, invalid: invalid }.to_json }.to raise_error Encoding::UndefinedConversionError
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'invalid body, valid message' do
|
31
|
+
stub_request(:get, 'http://local.ch')
|
32
|
+
.to_return(status: 200, body: "{ text : '#{invalid}' }")
|
33
|
+
response = LHC.get('http://local.ch')
|
34
|
+
expect { LHC::Error.new(valid, response).to_s }.not_to raise_error # Encoding::CompatibilityError
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'valid body, invalid message' do
|
38
|
+
stub_request(:get, 'http://local.ch')
|
39
|
+
.to_return(status: 200, body: "{ text : '#{valid}' }")
|
40
|
+
response = LHC.get('http://local.ch')
|
41
|
+
expect { LHC::Error.new(invalid, response).to_s }.not_to raise_error # Encoding::CompatibilityError
|
42
|
+
end
|
43
|
+
# the other cases cannot be tested (for example what happens if the headers contain invalid data)
|
44
|
+
# because the mocking framework triggers the encoding error already
|
45
|
+
|
46
|
+
context 'some mocked response' do
|
47
|
+
let(:request) do
|
48
|
+
double('request',
|
49
|
+
method: 'GET',
|
50
|
+
url: 'http://example.com/sessions',
|
51
|
+
headers: { 'Bearer Token' => "aaaaaaaa-bbbb-cccc-dddd-eeee" },
|
52
|
+
options: { followlocation: true,
|
53
|
+
auth: { bearer: "aaaaaaaa-bbbb-cccc-dddd-eeee" },
|
54
|
+
params: { limit: 20 }, url: "http://example.com/sessions" })
|
55
|
+
end
|
56
|
+
|
57
|
+
let(:response) do
|
58
|
+
double('response',
|
59
|
+
request: request,
|
60
|
+
code: 500,
|
61
|
+
options: { return_code: :internal_error, response_headers: "" },
|
62
|
+
body: '{"status":500,"message":"undefined"}')
|
63
|
+
end
|
64
|
+
|
65
|
+
subject { LHC::Error.new('The error message', response) }
|
66
|
+
|
67
|
+
it 'produces correct debug output' do
|
68
|
+
expect(subject.to_s.split("\n")).to eq(<<-MSG.strip_heredoc.split("\n"))
|
69
|
+
GET http://example.com/sessions
|
70
|
+
Options: {:followlocation=>true, :auth=>{:bearer=>"aaaaaaaa-bbbb-cccc-dddd-eeee"}, :params=>{:limit=>20}, :url=>"http://example.com/sessions"}
|
71
|
+
Headers: {"Bearer Token"=>"aaaaaaaa-bbbb-cccc-dddd-eeee"}
|
72
|
+
Response Code: 500 (internal_error)
|
73
|
+
Response Options: {:return_code=>:internal_error, :response_headers=>""}
|
74
|
+
{"status":500,"message":"undefined"}
|
75
|
+
The error message
|
76
|
+
MSG
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe LHC do
|
6
|
+
include ActionDispatch::TestProcess
|
7
|
+
|
8
|
+
context 'form' do
|
9
|
+
it 'formats requests to be application/x-www-form-urlencoded' do
|
10
|
+
stub = stub_request(:post, 'http://local.ch/')
|
11
|
+
.with(body: 'client_id=1234&client_secret=4567&grant_type=client_credentials')
|
12
|
+
.with(headers: { 'Content-Type': 'application/x-www-form-urlencoded' })
|
13
|
+
.to_return(status: 200)
|
14
|
+
|
15
|
+
LHC.form.post(
|
16
|
+
'http://local.ch',
|
17
|
+
body: {
|
18
|
+
client_id: '1234',
|
19
|
+
client_secret: '4567',
|
20
|
+
grant_type: 'client_credentials'
|
21
|
+
}
|
22
|
+
)
|
23
|
+
|
24
|
+
expect(stub).to have_been_requested
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe LHC do
|
6
|
+
context 'formats' do
|
7
|
+
it 'adds Content-Type, Accept and Accept-Charset Headers to the request' do
|
8
|
+
stub_request(:get, "http://local.ch/")
|
9
|
+
.with(headers: {
|
10
|
+
'Accept' => 'application/json,application/vnd.api+json',
|
11
|
+
'Content-Type' => 'application/json; charset=utf-8',
|
12
|
+
'Accept-Charset' => 'utf-8'
|
13
|
+
})
|
14
|
+
.to_return(body: {}.to_json)
|
15
|
+
LHC.json.get('http://local.ch')
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'header key as symbol' do
|
19
|
+
it 'raises an error when trying to set content-type header even though the format is used' do
|
20
|
+
expect(lambda {
|
21
|
+
LHC.post(
|
22
|
+
'http://local.ch',
|
23
|
+
headers: {
|
24
|
+
'Content-Type': 'multipart/form-data'
|
25
|
+
}
|
26
|
+
)
|
27
|
+
}).to raise_error 'Content-Type header is not allowed for formatted requests!\nSee https://github.com/local-ch/lhc#formats for more information.'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'raises an error when trying to set accept header even though the format is used' do
|
31
|
+
expect(lambda {
|
32
|
+
LHC.post(
|
33
|
+
'http://local.ch',
|
34
|
+
headers: {
|
35
|
+
'Accept': 'multipart/form-data'
|
36
|
+
}
|
37
|
+
)
|
38
|
+
}).to raise_error 'Accept header is not allowed for formatted requests!\nSee https://github.com/local-ch/lhc#formats for more information.'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'header key as string' do
|
43
|
+
it 'raises an error when trying to set content-type header even though the format is used' do
|
44
|
+
expect(lambda {
|
45
|
+
LHC.post(
|
46
|
+
'http://local.ch',
|
47
|
+
headers: {
|
48
|
+
'Content-Type' => 'multipart/form-data'
|
49
|
+
}
|
50
|
+
)
|
51
|
+
}).to raise_error 'Content-Type header is not allowed for formatted requests!\nSee https://github.com/local-ch/lhc#formats for more information.'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'raises an error when trying to set accept header even though the format is used' do
|
55
|
+
expect(lambda {
|
56
|
+
LHC.post(
|
57
|
+
'http://local.ch',
|
58
|
+
headers: {
|
59
|
+
'Accept' => 'multipart/form-data'
|
60
|
+
}
|
61
|
+
)
|
62
|
+
}).to raise_error 'Accept header is not allowed for formatted requests!\nSee https://github.com/local-ch/lhc#formats for more information.'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|