lhc 12.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ module LHC
6
+ module BasicMethodsConcern
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ def request(options)
11
+ if options.is_a? Array
12
+ parallel_requests(options)
13
+ else
14
+ LHC::Request.new(options).response
15
+ end
16
+ end
17
+
18
+ [:get, :post, :put, :delete].each do |http_method|
19
+ define_method(http_method) do |url, options = {}|
20
+ request(options.merge(
21
+ url: url,
22
+ method: http_method
23
+ ))
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def parallel_requests(options)
30
+ hydra = Typhoeus::Hydra.new # do not use memoization !
31
+ requests = []
32
+ options.each do |option|
33
+ request = LHC::Request.new(option, false)
34
+ requests << request
35
+ hydra.queue request.raw unless request.response.present?
36
+ end
37
+ hydra.run
38
+ requests.map(&:response)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ module LHC
6
+ module ConfigurationConcern
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ def config
11
+ LHC::Config.instance
12
+ end
13
+
14
+ def configure
15
+ LHC::Config.instance.reset
16
+ yield config
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ module LHC
6
+ module FixInvalidEncodingConcern
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ # fix strings that contain non-UTF8 encoding in a forceful way
11
+ # should none of the fix-attempts be successful,
12
+ # an empty string is returned instead
13
+ def fix_invalid_encoding(string)
14
+ return string unless string.is_a?(String)
15
+ result = string.dup
16
+
17
+ # we assume it's ISO-8859-1 first
18
+ if !result.valid_encoding? || !utf8?(result)
19
+ result.encode!('UTF-8', 'ISO-8859-1', invalid: :replace, undef: :replace, replace: '')
20
+ end
21
+
22
+ # if it's still an issue, try with BINARY
23
+ if !result.valid_encoding? || !utf8?(result)
24
+ result.encode!('UTF-8', 'BINARY', invalid: :replace, undef: :replace, replace: '')
25
+ end
26
+
27
+ # if its STILL an issue, return an empty string :(
28
+ if !result.valid_encoding? || !utf8?(result)
29
+ result = ""
30
+ end
31
+
32
+ result
33
+ end
34
+
35
+ private
36
+
37
+ def utf8?(string)
38
+ string.encoding == Encoding::UTF_8
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LHC
4
+ module FormatsConcern
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def form
9
+ LHC::Formats::Form
10
+ end
11
+
12
+ def json
13
+ LHC::Formats::JSON
14
+ end
15
+
16
+ def multipart
17
+ LHC::Formats::Multipart
18
+ end
19
+
20
+ def plain
21
+ LHC::Formats::Plain
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+ require 'lhc/version'
5
+
6
+ module LHC
7
+ class Request
8
+ module UserAgentConcern
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ Typhoeus::Config.user_agent = begin
13
+ version = LHC::VERSION
14
+ application = nil
15
+ if defined?(Rails)
16
+ app_class = Rails.application.class
17
+ application = (ActiveSupport.gem_version >= Gem::Version.new('6.0.0')) ? app_class.module_parent_name : app_class.parent_name
18
+ end
19
+
20
+ "LHC (#{[version, application].compact.join('; ')}) [https://github.com/local-ch/lhc]"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+
5
+ class LHC::Config
6
+ include Singleton
7
+
8
+ def initialize
9
+ @endpoints = {}
10
+ @placeholders = {}
11
+ end
12
+
13
+ def endpoint(name, url, options = {})
14
+ name = name.to_sym
15
+ raise 'Endpoint already exists for that name' if @endpoints[name]
16
+ @endpoints[name] = LHC::Endpoint.new(url, options)
17
+ end
18
+
19
+ def endpoints
20
+ @endpoints.dup
21
+ end
22
+
23
+ def placeholder(name, value)
24
+ name = name.to_sym
25
+ raise 'Placeholder already exists for that name' if @placeholders[name]
26
+ @placeholders[name] = value
27
+ end
28
+
29
+ def placeholders
30
+ @placeholders.dup
31
+ end
32
+
33
+ def interceptors
34
+ (@interceptors || []).dup
35
+ end
36
+
37
+ def interceptors=(interceptors)
38
+ raise 'Default interceptors already set and can only be set once' if @interceptors
39
+ @interceptors = interceptors
40
+ end
41
+
42
+ def reset
43
+ @endpoints = {}
44
+ @placeholders = {}
45
+ @interceptors = nil
46
+ end
47
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'addressable/template'
4
+
5
+ # An endpoint is an url that leads to a backend resource.
6
+ # The url can also be an url-template (https://tools.ietf.org/html/rfc6570).
7
+ class LHC::Endpoint
8
+ attr_accessor :url
9
+ attr_writer :options
10
+
11
+ def initialize(url, options = nil)
12
+ self.url = url
13
+ self.options = options
14
+ end
15
+
16
+ def uri
17
+ @uri ||= Addressable::Template.new(url)
18
+ end
19
+
20
+ def compile(params)
21
+ context = LHC.config.placeholders.deep_dup
22
+ context.merge!(params) if params.is_a?(Hash)
23
+ expanded = uri.partial_expand(context)
24
+
25
+ if expanded.variables.empty?
26
+ expanded.pattern
27
+ else
28
+ raise("Compilation incomplete. Unable to find value for #{expanded.variables.join(', ')}.")
29
+ end
30
+ end
31
+
32
+ # Endpoint options are immutable
33
+ def options
34
+ @options.deep_dup
35
+ end
36
+
37
+ # Removes keys from provided params hash
38
+ # when they are used for interpolation.
39
+ def remove_interpolated_params!(params)
40
+ params ||= {}
41
+ removed = params.slice(*placeholders)
42
+ params.except!(*placeholders)
43
+
44
+ removed
45
+ end
46
+
47
+ # Returns all placeholders found in the url-template.
48
+ # They are alphabetically sorted.
49
+ def placeholders
50
+ uri.variables.sort.map(&:to_sym)
51
+ end
52
+
53
+ # Compares a concrete url with a template
54
+ # Returns true if concrete url is covered by the template
55
+ # Example: {+datastore}/contracts/{id} == http://local.ch/contracts/1
56
+ def match?(url)
57
+ return true if url == uri.pattern
58
+ match_data = match_data(url)
59
+ return false if match_data.nil?
60
+
61
+ first = match_data.values.first
62
+ last = match_data.values.last
63
+ url_format = File.extname(url)
64
+
65
+ # eliminate false positives in form:
66
+ # http://host/feedbacks matches {+service}/{entry_id}/feedbacks (service: http:/, entry_id: host)
67
+ first&.match(%{https?:/$}).nil? &&
68
+ # eliminates false positives in form:
69
+ # http://host/entries/123.json matches {+service}/entries/{id} (service: http://host, id: 123.json)
70
+ (url_format.blank? || !last&.ends_with?(url_format))
71
+ end
72
+
73
+ # Extracts the values from url and
74
+ # creates params according to template
75
+ def values_as_params(url)
76
+ match_data = match_data(url)
77
+ return if match_data.nil?
78
+ Hash[match_data.variables.map(&:to_sym).zip(match_data.values)]
79
+ end
80
+
81
+ # Checks if the name has a match in the current context
82
+ def find_value(name, mapping)
83
+ context = LHC.config.placeholders.deep_dup
84
+ context.merge!(mapping)
85
+
86
+ context[name]
87
+ end
88
+
89
+ # Compares a concrete url with a template
90
+ # Returns true if concrete url is covered by the template
91
+ # Example: {+datastore}/contracts/{id} == http://local.ch/contracts/1
92
+ def self.match?(url, template)
93
+ new(template).match?(url)
94
+ end
95
+
96
+ # Returns all placeholders found in the url-template.
97
+ # They are alphabetically sorted.
98
+ def self.placeholders(template)
99
+ new(template).placeholders
100
+ end
101
+
102
+ # Extracts the values from url and
103
+ # creates params according to template
104
+ def self.values_as_params(template, url)
105
+ raise("#{url} does not match the template: #{template}") if !match?(url, template)
106
+ new(template).values_as_params(url)
107
+ end
108
+
109
+ private
110
+
111
+ def match_data(url)
112
+ parsed = URI.parse(url)
113
+ parsed.query = parsed.fragment = nil
114
+
115
+ uri.match(parsed)
116
+ rescue URI::InvalidURIError
117
+ nil
118
+ end
119
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LHC::Error < StandardError
4
+ include LHC::FixInvalidEncodingConcern
5
+
6
+ attr_accessor :response, :_message
7
+
8
+ def self.map
9
+ {
10
+ 400 => LHC::BadRequest,
11
+ 401 => LHC::Unauthorized,
12
+ 402 => LHC::PaymentRequired,
13
+ 403 => LHC::Forbidden,
14
+ 404 => LHC::NotFound,
15
+ 405 => LHC::MethodNotAllowed,
16
+ 406 => LHC::NotAcceptable,
17
+ 407 => LHC::ProxyAuthenticationRequired,
18
+ 408 => LHC::RequestTimeout,
19
+ 409 => LHC::Conflict,
20
+ 410 => LHC::Gone,
21
+ 411 => LHC::LengthRequired,
22
+ 412 => LHC::PreconditionFailed,
23
+ 413 => LHC::RequestEntityTooLarge,
24
+ 414 => LHC::RequestUriToLong,
25
+ 415 => LHC::UnsupportedMediaType,
26
+ 416 => LHC::RequestedRangeNotSatisfiable,
27
+ 417 => LHC::ExpectationFailed,
28
+ 422 => LHC::UnprocessableEntity,
29
+ 423 => LHC::Locked,
30
+ 424 => LHC::FailedDependency,
31
+ 426 => LHC::UpgradeRequired,
32
+
33
+ 500 => LHC::InternalServerError,
34
+ 501 => LHC::NotImplemented,
35
+ 502 => LHC::BadGateway,
36
+ 503 => LHC::ServiceUnavailable,
37
+ 504 => LHC::GatewayTimeout,
38
+ 505 => LHC::HttpVersionNotSupported,
39
+ 507 => LHC::InsufficientStorage,
40
+ 510 => LHC::NotExtended
41
+ }
42
+ end
43
+
44
+ def self.find(response)
45
+ return LHC::Timeout if response.timeout?
46
+ status_code = response.code.to_s[0..2].to_i
47
+ error = map[status_code]
48
+ error ||= LHC::UnknownError
49
+ error
50
+ end
51
+
52
+ def self.dup
53
+ self
54
+ end
55
+
56
+ def initialize(message, response)
57
+ super(message)
58
+ self._message = message
59
+ self.response = response
60
+ end
61
+
62
+ def self.to_a
63
+ [self]
64
+ end
65
+
66
+ def to_s
67
+ return response if response.is_a?(String)
68
+ request = response.request
69
+ debug = []
70
+ debug << [request.method, request.url].map { |str| self.class.fix_invalid_encoding(str) }.join(' ')
71
+ debug << "Options: #{request.options}"
72
+ debug << "Headers: #{request.headers}"
73
+ debug << "Response Code: #{response.code} (#{response.options[:return_code]})"
74
+ debug << "Response Options: #{response.options}"
75
+ debug << response.body
76
+ debug << _message
77
+
78
+ debug.map { |str| self.class.fix_invalid_encoding(str) }.join("\n")
79
+ end
80
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LHC::ClientError < LHC::Error
4
+ end
5
+
6
+ class LHC::BadRequest < LHC::ClientError
7
+ end
8
+
9
+ class LHC::Unauthorized < LHC::ClientError
10
+ end
11
+
12
+ class LHC::PaymentRequired < LHC::ClientError
13
+ end
14
+
15
+ class LHC::Forbidden < LHC::ClientError
16
+ end
17
+
18
+ class LHC::Forbidden < LHC::ClientError
19
+ end
20
+
21
+ class LHC::NotFound < LHC::ClientError
22
+ end
23
+
24
+ class LHC::MethodNotAllowed < LHC::ClientError
25
+ end
26
+
27
+ class LHC::NotAcceptable < LHC::ClientError
28
+ end
29
+
30
+ class LHC::ProxyAuthenticationRequired < LHC::ClientError
31
+ end
32
+
33
+ class LHC::RequestTimeout < LHC::ClientError
34
+ end
35
+
36
+ class LHC::Conflict < LHC::ClientError
37
+ end
38
+
39
+ class LHC::Gone < LHC::ClientError
40
+ end
41
+
42
+ class LHC::LengthRequired < LHC::ClientError
43
+ end
44
+
45
+ class LHC::PreconditionFailed < LHC::ClientError
46
+ end
47
+
48
+ class LHC::RequestEntityTooLarge < LHC::ClientError
49
+ end
50
+
51
+ class LHC::RequestUriToLong < LHC::ClientError
52
+ end
53
+
54
+ class LHC::UnsupportedMediaType < LHC::ClientError
55
+ end
56
+
57
+ class LHC::RequestedRangeNotSatisfiable < LHC::ClientError
58
+ end
59
+
60
+ class LHC::ExpectationFailed < LHC::ClientError
61
+ end
62
+
63
+ class LHC::UnprocessableEntity < LHC::ClientError
64
+ end
65
+
66
+ class LHC::Locked < LHC::ClientError
67
+ end
68
+
69
+ class LHC::FailedDependency < LHC::ClientError
70
+ end
71
+
72
+ class LHC::UpgradeRequired < LHC::ClientError
73
+ end