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
data/lib/lhc/request.rb
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'uri'
|
|
4
|
+
require 'active_support/core_ext/object/deep_dup'
|
|
5
|
+
require 'lhc/concerns/lhc/request/user_agent_concern'
|
|
6
|
+
|
|
7
|
+
# The request is doing an http-request using typhoeus.
|
|
8
|
+
# It provides functionalities to access and alter request data
|
|
9
|
+
# and it communicates with interceptors.
|
|
10
|
+
class LHC::Request
|
|
11
|
+
include UserAgentConcern
|
|
12
|
+
|
|
13
|
+
TYPHOEUS_OPTIONS ||= [:params, :method, :body, :headers, :follow_location, :params_encoding]
|
|
14
|
+
|
|
15
|
+
attr_accessor :response, :options, :raw, :format, :error_handler, :errors_ignored, :source
|
|
16
|
+
|
|
17
|
+
def initialize(options, self_executing = true)
|
|
18
|
+
self.errors_ignored = (options.fetch(:ignore, []) || []).to_a.compact
|
|
19
|
+
self.source = options&.dig(:source)
|
|
20
|
+
self.options = format!(options.deep_dup || {})
|
|
21
|
+
self.error_handler = options.delete :rescue
|
|
22
|
+
use_configured_endpoint!
|
|
23
|
+
generate_url_from_template!
|
|
24
|
+
self.interceptors = LHC::Interceptors.new(self)
|
|
25
|
+
interceptors.intercept(:before_raw_request)
|
|
26
|
+
self.raw = create_request
|
|
27
|
+
interceptors.intercept(:before_request)
|
|
28
|
+
run! if self_executing && !response
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def url
|
|
32
|
+
raw.base_url || options[:url]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def method
|
|
36
|
+
(raw.options[:method] || options[:method] || :get).to_sym
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def headers
|
|
40
|
+
raw.options.fetch(:headers, nil) || raw.options[:headers] = {}
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def params
|
|
44
|
+
raw.options.fetch(:params, nil) || raw.options[:params] = {}
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def error_ignored?
|
|
48
|
+
ignore_error?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def run!
|
|
52
|
+
raw.run
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
attr_accessor :interceptors
|
|
58
|
+
|
|
59
|
+
def format!(options)
|
|
60
|
+
self.format = options.delete(:format) || LHC::Formats::JSON.new
|
|
61
|
+
format.format_options(options)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def optionally_encoded_url(options)
|
|
65
|
+
return options[:url] unless options.fetch(:url_encoding, true)
|
|
66
|
+
encode_url(options[:url])
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def create_request
|
|
70
|
+
request = Typhoeus::Request.new(
|
|
71
|
+
optionally_encoded_url(options),
|
|
72
|
+
translate_body(typhoeusize(options))
|
|
73
|
+
)
|
|
74
|
+
request.on_headers do
|
|
75
|
+
interceptors.intercept(:after_request)
|
|
76
|
+
interceptors.intercept(:before_response)
|
|
77
|
+
end
|
|
78
|
+
request.on_complete { |response| on_complete(response) }
|
|
79
|
+
request
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def translate_body(options)
|
|
83
|
+
return options if options.fetch(:body, nil).blank?
|
|
84
|
+
options[:body] = format.to_body(options[:body])
|
|
85
|
+
options
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def encode_url(url)
|
|
89
|
+
return url if url.nil?
|
|
90
|
+
URI.escape(url)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def typhoeusize(options)
|
|
94
|
+
options = options.deep_dup
|
|
95
|
+
easy = Ethon::Easy.new
|
|
96
|
+
options.delete(:url)
|
|
97
|
+
options.each do |key, _v|
|
|
98
|
+
next if TYPHOEUS_OPTIONS.include? key
|
|
99
|
+
method = "#{key}="
|
|
100
|
+
options.delete key unless easy.respond_to?(method)
|
|
101
|
+
end
|
|
102
|
+
options
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Get configured endpoint and use it for doing the request.
|
|
106
|
+
# Explicit request options are overriding configured options.
|
|
107
|
+
def use_configured_endpoint!
|
|
108
|
+
endpoint = LHC.config.endpoints[options[:url]]
|
|
109
|
+
return unless endpoint
|
|
110
|
+
# explicit options override endpoint options
|
|
111
|
+
new_options = endpoint.options.deep_merge(options)
|
|
112
|
+
# set new options
|
|
113
|
+
self.options = new_options
|
|
114
|
+
options[:url] = endpoint.url
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Generates URL from a URL template
|
|
118
|
+
def generate_url_from_template!
|
|
119
|
+
endpoint = LHC::Endpoint.new(options[:url])
|
|
120
|
+
params =
|
|
121
|
+
if format && options[:body].present? && options[:body].respond_to?(:as_json) && options[:body].as_json.is_a?(Hash)
|
|
122
|
+
options[:body].as_json.merge(options[:params] || {}).deep_symbolize_keys
|
|
123
|
+
else
|
|
124
|
+
options[:params]
|
|
125
|
+
end
|
|
126
|
+
options[:url] = endpoint.compile(params)
|
|
127
|
+
endpoint.remove_interpolated_params!(options[:params])
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def on_complete(response)
|
|
131
|
+
self.response = LHC::Response.new(response, self)
|
|
132
|
+
interceptors.intercept(:after_response)
|
|
133
|
+
handle_error(self.response) unless self.response.success?
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def handle_error(response)
|
|
137
|
+
return if ignore_error?
|
|
138
|
+
throw_error(response) unless error_handler
|
|
139
|
+
response.body_replacement = error_handler.call(response)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def ignore_error?
|
|
143
|
+
@ignore_error ||= begin
|
|
144
|
+
errors_ignored.detect do |ignored_error|
|
|
145
|
+
error <= ignored_error
|
|
146
|
+
end.present?
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def error
|
|
151
|
+
@error ||= LHC::Error.find(response)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def throw_error(response)
|
|
155
|
+
raise error.new(error, response)
|
|
156
|
+
end
|
|
157
|
+
end
|
data/lib/lhc/response.rb
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support/core_ext/module'
|
|
4
|
+
|
|
5
|
+
# The response contains the raw response (typhoeus)
|
|
6
|
+
# and provides functionality to access response data.
|
|
7
|
+
class LHC::Response
|
|
8
|
+
autoload :Data, 'lhc/response/data'
|
|
9
|
+
|
|
10
|
+
attr_accessor :request, :body_replacement
|
|
11
|
+
attr_reader :from_cache
|
|
12
|
+
|
|
13
|
+
delegate :effective_url, :code, :headers, :options, :mock, :success?, to: :raw
|
|
14
|
+
delegate :error_ignored?, to: :request
|
|
15
|
+
alias from_cache? from_cache
|
|
16
|
+
|
|
17
|
+
# A response is initalized with the underlying raw response (typhoeus in our case)
|
|
18
|
+
# and the associated request.
|
|
19
|
+
def initialize(raw, request, from_cache: false)
|
|
20
|
+
self.request = request
|
|
21
|
+
self.raw = raw
|
|
22
|
+
@from_cache = from_cache
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def data
|
|
26
|
+
@data ||= body.present? ? LHC::Response::Data.new(self) : nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def [](key)
|
|
30
|
+
data[key]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def body
|
|
34
|
+
body_replacement || raw.body.presence
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Provides response time in seconds
|
|
38
|
+
def time
|
|
39
|
+
raw.time || 0
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Provides response time in milliseconds
|
|
43
|
+
def time_ms
|
|
44
|
+
time * 1000
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def timeout?
|
|
48
|
+
raw.timed_out?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def format
|
|
52
|
+
return LHC::Formats::JSON.new if request.nil?
|
|
53
|
+
request.format
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
attr_accessor :raw
|
|
59
|
+
|
|
60
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class LHC::Response::Data
|
|
4
|
+
autoload :Base, 'lhc/response/data/base'
|
|
5
|
+
autoload :Item, 'lhc/response/data/item'
|
|
6
|
+
autoload :Collection, 'lhc/response/data/collection'
|
|
7
|
+
|
|
8
|
+
include LHC::Response::Data::Base
|
|
9
|
+
|
|
10
|
+
def initialize(response, data: nil)
|
|
11
|
+
@response = response
|
|
12
|
+
@data = data
|
|
13
|
+
|
|
14
|
+
if as_json.is_a?(Hash)
|
|
15
|
+
@base = LHC::Response::Data::Item.new(response, data: data)
|
|
16
|
+
elsif as_json.is_a?(Array)
|
|
17
|
+
@base = LHC::Response::Data::Collection.new(response, data: data)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def method_missing(method, *args, &block) # rubocop:disable Style/MethodMissingSuper
|
|
22
|
+
@base.send(method, *args, &block)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
26
|
+
@base.respond_to?(method_name, include_private) || super
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Response data is data provided through the response body
|
|
4
|
+
# but made accssible in the ruby world
|
|
5
|
+
module LHC::Response::Data::Base
|
|
6
|
+
def as_json
|
|
7
|
+
@json ||= (@data || response.format.as_json(response.body))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def as_open_struct
|
|
11
|
+
@open_struct ||=
|
|
12
|
+
if @data
|
|
13
|
+
JSON.parse(@data.to_json, object_class: OpenStruct)
|
|
14
|
+
else
|
|
15
|
+
response.format.as_open_struct(response.body)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
attr_reader :response
|
|
22
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class LHC::Response::Data::Collection < Array
|
|
4
|
+
include LHC::Response::Data::Base
|
|
5
|
+
|
|
6
|
+
def initialize(response, data: nil)
|
|
7
|
+
@response = response
|
|
8
|
+
@data = data
|
|
9
|
+
|
|
10
|
+
super(
|
|
11
|
+
as_json.map do |i|
|
|
12
|
+
LHC::Response::Data.new(response, data: i)
|
|
13
|
+
end
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class LHC::Response::Data::Item < OpenStruct
|
|
4
|
+
include LHC::Response::Data::Base
|
|
5
|
+
|
|
6
|
+
def initialize(response, data: nil)
|
|
7
|
+
@response = response
|
|
8
|
+
@data = data
|
|
9
|
+
|
|
10
|
+
set_dynamic_accessor_methods
|
|
11
|
+
|
|
12
|
+
super(as_json)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def [](key)
|
|
16
|
+
@hash ||= as_json.with_indifferent_access
|
|
17
|
+
@hash[key]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def set_dynamic_accessor_methods
|
|
23
|
+
as_json.keys.each do |key|
|
|
24
|
+
define_singleton_method key do |*args|
|
|
25
|
+
as_open_struct.send key, *args
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/lhc/rspec.rb
ADDED
data/lib/lhc/version.rb
ADDED
data/script/ci/build.sh
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/bin/bash -e
|
|
2
|
+
|
|
3
|
+
# custom vars
|
|
4
|
+
# RUBY = ruby-1.9.3-p125
|
|
5
|
+
# GEMSET = location-app-${GitHub pull request id|branch name}
|
|
6
|
+
# standard vars
|
|
7
|
+
|
|
8
|
+
if [ -z "$SKIP_RVM" ]; then
|
|
9
|
+
[[ -s "/usr/local/rvm/scripts/rvm" ]] && . "/usr/local/rvm/scripts/rvm"
|
|
10
|
+
RUBY=${RUBY:-ruby-2.1.2}
|
|
11
|
+
GEMSET=${GEMSET:-LHC}
|
|
12
|
+
rvm use ${RUBY}@${GEMSET} --create
|
|
13
|
+
gem install bundler --no-rdoc --no-ri
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
bundle install --local --quiet || bundle install --quiet
|
|
17
|
+
RAILS_ENV=test bundle exec rspec
|
|
18
|
+
bundle exec rspec non_rails_spec
|
|
19
|
+
rvm --force gemset delete ${RUBY}@${GEMSET}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC do
|
|
6
|
+
context 'delete' do
|
|
7
|
+
let(:feedback) do
|
|
8
|
+
{
|
|
9
|
+
recommended: true,
|
|
10
|
+
source_id: 'aaa',
|
|
11
|
+
content_ad_id: '1z-5r1fkaj'
|
|
12
|
+
}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
before(:each) do
|
|
16
|
+
stub_request(:delete, "http://datastore/v2/feedbacks/12121")
|
|
17
|
+
.to_return(status: 200, body: feedback.to_json, headers: { 'Content-Encoding' => 'UTF-8' })
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'does a delete request when providing a complete url' do
|
|
21
|
+
LHC.delete('http://datastore/v2/feedbacks/12121')
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'makes response data available in a rails way' do
|
|
25
|
+
response = LHC.delete('http://datastore/v2/feedbacks/12121')
|
|
26
|
+
expect(response.data.recommended).to eq true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'provides response headers' do
|
|
30
|
+
response = LHC.delete('http://datastore/v2/feedbacks/12121')
|
|
31
|
+
expect(response.headers).to be_present
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
describe LHC do
|
|
6
|
+
context 'get' do
|
|
7
|
+
before(:each) do
|
|
8
|
+
stub_request(:get, 'http://datastore/v2/feedbacks?has_reviews=true')
|
|
9
|
+
.to_return(status: 200, body: { total: 99 }.to_json, headers: { 'Content-Encoding' => 'UTF-8' })
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let(:parameters) do
|
|
13
|
+
{ has_reviews: true }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'does a get request when providing a complete url' do
|
|
17
|
+
LHC.get('http://datastore/v2/feedbacks', params: parameters)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'does a get request when providing the name of a configured endpoint' do
|
|
21
|
+
url = 'http://{+datastore}/v2/feedbacks'
|
|
22
|
+
options = { params: { datastore: 'datastore' } }
|
|
23
|
+
LHC.configure { |c| c.endpoint(:feedbacks, url, options) }
|
|
24
|
+
LHC.get(:feedbacks, params: parameters)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'makes response data available in a rails way' do
|
|
28
|
+
response = LHC.get('http://datastore/v2/feedbacks', params: parameters)
|
|
29
|
+
expect(response.data.total).to eq 99
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'provides response headers' do
|
|
33
|
+
response = LHC.get('http://datastore/v2/feedbacks', params: parameters)
|
|
34
|
+
expect(response.headers).to be_present
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context 'get json' do
|
|
39
|
+
before(:each) do
|
|
40
|
+
stub_request(:get, 'http://datastore/v2/feedbacks').with(headers: { 'Content-Type' => 'application/json; charset=utf-8' })
|
|
41
|
+
.to_return(body: { some: 'json' }.to_json)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'requests json and parses response body' do
|
|
45
|
+
data = LHC.json.get('http://datastore/v2/feedbacks').data
|
|
46
|
+
expect(data.some).to eq 'json'
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|