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,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
|