lhc 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +36 -0
- data/Gemfile +11 -0
- data/README.md +116 -0
- data/Rakefile +25 -0
- data/docs/configuration.md +57 -0
- data/docs/exceptions.md +68 -0
- data/docs/interceptors.md +90 -0
- data/docs/request.md +24 -0
- data/docs/response.md +19 -0
- data/lhc.gemspec +30 -0
- data/lib/lhc.rb +16 -0
- data/lib/lhc/concerns/lhc/basic_methods.rb +42 -0
- data/lib/lhc/config.rb +45 -0
- data/lib/lhc/endpoint.rb +53 -0
- data/lib/lhc/error.rb +63 -0
- data/lib/lhc/errors/client_error.rb +73 -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/interceptor.rb +9 -0
- data/lib/lhc/interceptor_processor.rb +24 -0
- data/lib/lhc/request.rb +91 -0
- data/lib/lhc/response.rb +52 -0
- data/lib/lhc/version.rb +3 -0
- data/script/ci/build.sh +19 -0
- data/spec/basic_methods/delete_spec.rb +34 -0
- data/spec/basic_methods/get_spec.rb +37 -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/config/endpoints_spec.rb +49 -0
- data/spec/config/placeholders_spec.rb +32 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -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 +5 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -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 +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +14 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +34 -0
- data/spec/dummy/config/environments/production.rb +75 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/assets.rb +8 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +9 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +56 -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 +25 -0
- data/spec/endpoint/placeholders_spec.rb +14 -0
- data/spec/endpoint/remove_interpolated_params_spec.rb +16 -0
- data/spec/error/find_spec.rb +56 -0
- data/spec/error/response_spec.rb +17 -0
- data/spec/error/timeout_spec.rb +14 -0
- data/spec/interceptors/after_request_spec.rb +21 -0
- data/spec/interceptors/after_response_spec.rb +42 -0
- data/spec/interceptors/before_request_spec.rb +21 -0
- data/spec/interceptors/before_response_spec.rb +21 -0
- data/spec/interceptors/default_interceptors_spec.rb +15 -0
- data/spec/interceptors/define_spec.rb +29 -0
- data/spec/interceptors/response_competition_spec.rb +40 -0
- data/spec/interceptors/return_response_spec.rb +39 -0
- data/spec/rails_helper.rb +4 -0
- data/spec/request/error_handling_spec.rb +52 -0
- data/spec/request/headers_spec.rb +11 -0
- data/spec/request/option_dup_spec.rb +12 -0
- data/spec/request/parallel_requests_spec.rb +15 -0
- data/spec/request/url_patterns_spec.rb +19 -0
- data/spec/response/body_spec.rb +16 -0
- data/spec/response/code_spec.rb +16 -0
- data/spec/response/data_spec.rb +18 -0
- data/spec/response/headers_spec.rb +18 -0
- data/spec/response/success_spec.rb +12 -0
- data/spec/response/time_spec.rb +16 -0
- data/spec/spec_helper.rb +4 -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 +3 -0
- data/spec/support/reset_config.rb +7 -0
- data/spec/timeouts/no_signal_spec.rb +13 -0
- data/spec/timeouts/timings_spec.rb +59 -0
- metadata +313 -0
data/docs/response.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Response
|
2
|
+
===
|
3
|
+
|
4
|
+
```ruby
|
5
|
+
response.request #<LHC::Request> the associated request.
|
6
|
+
|
7
|
+
response.data #<OpenStruct> in case response body contains parsable JSON.
|
8
|
+
response.data.something.nested
|
9
|
+
|
10
|
+
response.body #<String>
|
11
|
+
|
12
|
+
response.code #<Fixnum>
|
13
|
+
|
14
|
+
response.headers #<Hash>
|
15
|
+
|
16
|
+
response.time #<Fixnum> Provides response time in ms.
|
17
|
+
|
18
|
+
response.timeout? #true|false
|
19
|
+
```
|
data/lhc.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
# Maintain your gem's version:
|
4
|
+
require "lhc/version"
|
5
|
+
|
6
|
+
# Describe your gem and declare its dependencies:
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "lhc"
|
9
|
+
s.version = LHC::VERSION
|
10
|
+
s.authors = ['local.ch']
|
11
|
+
s.email = ['ws-operations@local.ch']
|
12
|
+
s.homepage = 'https://github.com/local-ch/lhc'
|
13
|
+
s.summary = 'LocalHttpServices'
|
14
|
+
s.description = 'Rails gem wrapping typhoeus and providing additional features (like interceptors)'
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
18
|
+
s.require_paths = ['lib']
|
19
|
+
|
20
|
+
s.requirements << 'Ruby >= 1.9.2'
|
21
|
+
s.required_ruby_version = '>= 1.9.2'
|
22
|
+
|
23
|
+
s.add_dependency 'typhoeus'
|
24
|
+
|
25
|
+
s.add_development_dependency 'rspec-rails', '>= 3.0.0'
|
26
|
+
s.add_development_dependency 'rails', '~> 4.1.1'
|
27
|
+
s.add_development_dependency 'webmock'
|
28
|
+
s.add_development_dependency 'geminabox'
|
29
|
+
s.add_development_dependency 'pry'
|
30
|
+
end
|
data/lib/lhc.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Dir[File.dirname(__FILE__) + '/lhc/concerns/lhc/*.rb'].sort.each {|file| require file }
|
2
|
+
|
3
|
+
module LHC
|
4
|
+
include BasicMethods
|
5
|
+
|
6
|
+
def self.config
|
7
|
+
LHC::Config.instance
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.configure
|
11
|
+
LHC::Config.instance.reset
|
12
|
+
yield config
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Gem.find_files('lhc/**/*.rb').sort.each { |path| require path }
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module LHC
|
4
|
+
|
5
|
+
module BasicMethods
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
|
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.hydra
|
31
|
+
requests = []
|
32
|
+
options.each do |options|
|
33
|
+
request = LHC::Request.new(options, false)
|
34
|
+
requests << request
|
35
|
+
hydra.queue request.raw
|
36
|
+
end
|
37
|
+
hydra.run
|
38
|
+
requests.map(&:response)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/lhc/config.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
class LHC::Config
|
4
|
+
include Singleton
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@endpoints = {}
|
8
|
+
@placeholders = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def endpoint(name, url, options = {})
|
12
|
+
name = name.to_sym
|
13
|
+
fail 'Endpoint already exists for that name' if @endpoints[name]
|
14
|
+
@endpoints[name] = LHC::Endpoint.new(url, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def endpoints
|
18
|
+
@endpoints.dup
|
19
|
+
end
|
20
|
+
|
21
|
+
def placeholder(name, value)
|
22
|
+
name = name.to_sym
|
23
|
+
fail 'Placeholder already exists for that name' if @placeholders[name]
|
24
|
+
@placeholders[name] = value
|
25
|
+
end
|
26
|
+
|
27
|
+
def placeholders
|
28
|
+
@placeholders.dup
|
29
|
+
end
|
30
|
+
|
31
|
+
def interceptors
|
32
|
+
(@interceptors || []).dup
|
33
|
+
end
|
34
|
+
|
35
|
+
def interceptors=(interceptors)
|
36
|
+
fail 'Default interceptors already set and can only be set once' if @interceptors
|
37
|
+
@interceptors = interceptors
|
38
|
+
end
|
39
|
+
|
40
|
+
def reset
|
41
|
+
@endpoints = {}
|
42
|
+
@placeholders = {}
|
43
|
+
@interceptors = nil
|
44
|
+
end
|
45
|
+
end
|
data/lib/lhc/endpoint.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# An endpoint is an url that leads to a backend resource.
|
2
|
+
# The url can also be an url-template.
|
3
|
+
class LHC::Endpoint
|
4
|
+
|
5
|
+
PLACEHOLDER = /\:[A-Z,a-z,_,-]+/
|
6
|
+
|
7
|
+
attr_accessor :url, :options
|
8
|
+
|
9
|
+
def initialize(url, options = nil)
|
10
|
+
self.url = url
|
11
|
+
self.options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def compile(params)
|
15
|
+
url.gsub(PLACEHOLDER) do |match|
|
16
|
+
replacement = if params.is_a? Proc
|
17
|
+
params.call(match)
|
18
|
+
else
|
19
|
+
find_value(match, params)
|
20
|
+
end
|
21
|
+
replacement || fail("Compilation incomplete. Unable to find value for #{match.gsub(':', '')}.")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Removes keys from provided params hash
|
26
|
+
# when they are used for interpolation.
|
27
|
+
def remove_interpolated_params!(params)
|
28
|
+
params ||= {}
|
29
|
+
removed = {}
|
30
|
+
url.scan(PLACEHOLDER) do |match|
|
31
|
+
match = match.gsub(/^\:/, '')
|
32
|
+
if value = find_value(match, params)
|
33
|
+
removed[match.to_sym] = value
|
34
|
+
params.delete(match.to_sym)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
removed
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns all placeholders found in the url-template.
|
41
|
+
# They are alphabetically sorted.
|
42
|
+
def placeholders
|
43
|
+
url.scan(PLACEHOLDER).sort
|
44
|
+
end
|
45
|
+
|
46
|
+
# Find a value for a placeholder either in the configuration
|
47
|
+
# or in the provided params.
|
48
|
+
def find_value(match, params)
|
49
|
+
params ||= {}
|
50
|
+
match = match.gsub(/^\:/, '').to_sym
|
51
|
+
params[match] || LHC.config.placeholders[match]
|
52
|
+
end
|
53
|
+
end
|
data/lib/lhc/error.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
class LHC::Error < StandardError
|
2
|
+
|
3
|
+
attr_accessor :response
|
4
|
+
|
5
|
+
def self.map
|
6
|
+
{
|
7
|
+
400 => LHC::BadRequest,
|
8
|
+
401 => LHC::Unauthorized,
|
9
|
+
402 => LHC::PaymentRequired,
|
10
|
+
403 => LHC::Forbidden,
|
11
|
+
404 => LHC::NotFound,
|
12
|
+
405 => LHC::MethodNotAllowed,
|
13
|
+
406 => LHC::NotAcceptable,
|
14
|
+
407 => LHC::ProxyAuthenticationRequired,
|
15
|
+
408 => LHC::RequestTimeout,
|
16
|
+
409 => LHC::Conflict,
|
17
|
+
410 => LHC::Gone,
|
18
|
+
411 => LHC::LengthRequired,
|
19
|
+
412 => LHC::PreconditionFailed,
|
20
|
+
413 => LHC::RequestEntityTooLarge,
|
21
|
+
414 => LHC::RequestUriToLong,
|
22
|
+
415 => LHC::UnsupportedMediaType,
|
23
|
+
416 => LHC::RequestedRangeNotSatisfiable,
|
24
|
+
417 => LHC::ExpectationFailed,
|
25
|
+
422 => LHC::UnprocessableEntity,
|
26
|
+
423 => LHC::Locked,
|
27
|
+
424 => LHC::FailedDependency,
|
28
|
+
426 => LHC::UpgradeRequired,
|
29
|
+
|
30
|
+
500 => LHC::InternalServerError,
|
31
|
+
501 => LHC::NotImplemented,
|
32
|
+
502 => LHC::BadGateway,
|
33
|
+
503 => LHC::ServiceUnavailable,
|
34
|
+
504 => LHC::GatewayTimeout,
|
35
|
+
505 => LHC::HttpVersionNotSupported,
|
36
|
+
507 => LHC::InsufficientStorage,
|
37
|
+
510 => LHC::NotExtended
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.find(response)
|
42
|
+
return LHC::Timeout if response.timeout?
|
43
|
+
status_code = response.code.to_s[0..2].to_i
|
44
|
+
error = map[status_code]
|
45
|
+
error ||= LHC::UnknownError
|
46
|
+
error
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize(message, response)
|
50
|
+
super(message)
|
51
|
+
self.response = response
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
request = response.request
|
56
|
+
debug = []
|
57
|
+
debug << "#{request.method} #{request.url}"
|
58
|
+
debug << "Params: #{request.options}"
|
59
|
+
debug << "Response Code: #{response.code}"
|
60
|
+
debug << response.body
|
61
|
+
debug.join("\n")
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../error'
|
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
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../error'
|
2
|
+
|
3
|
+
class LHC::ServerError < LHC::Error
|
4
|
+
end
|
5
|
+
|
6
|
+
class LHC::InternalServerError < LHC::ServerError
|
7
|
+
end
|
8
|
+
|
9
|
+
class LHC::NotImplemented < LHC::ServerError
|
10
|
+
end
|
11
|
+
|
12
|
+
class LHC::BadGateway < LHC::ServerError
|
13
|
+
end
|
14
|
+
|
15
|
+
class LHC::ServiceUnavailable < LHC::ServerError
|
16
|
+
end
|
17
|
+
|
18
|
+
class LHC::GatewayTimeout < LHC::ServerError
|
19
|
+
end
|
20
|
+
|
21
|
+
class LHC::HttpVersionNotSupported < LHC::ServerError
|
22
|
+
end
|
23
|
+
|
24
|
+
class LHC::InsufficientStorage < LHC::ServerError
|
25
|
+
end
|
26
|
+
|
27
|
+
class LHC::NotExtended < LHC::ServerError
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Handles interceptions during the lifecycle of a request
|
2
|
+
class LHC::InterceptorProcessor
|
3
|
+
|
4
|
+
attr_accessor :interceptors
|
5
|
+
|
6
|
+
# Intitalizes the processor and determines if global or local interceptors are used
|
7
|
+
def initialize(target)
|
8
|
+
options = target.options if target.is_a? LHC::Request
|
9
|
+
options ||= target.request.options if target.is_a? LHC::Response
|
10
|
+
self.interceptors = (options[:interceptors] || LHC.config.interceptors).map{ |i| i.new }
|
11
|
+
end
|
12
|
+
|
13
|
+
# Forwards messages to interceptors and handles provided responses.
|
14
|
+
def intercept(name, target)
|
15
|
+
interceptors.each do |interceptor|
|
16
|
+
result = interceptor.send(name, target)
|
17
|
+
if result.is_a? LHC::Response
|
18
|
+
fail 'Response already set from another interceptor' if @response
|
19
|
+
request = target.is_a?(LHC::Request) ? target : target.request
|
20
|
+
@response = request.response = result
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/lhc/request.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'typhoeus'
|
2
|
+
|
3
|
+
# The request is doing an http-request using typhoeus.
|
4
|
+
# It provides functionalities to access and alter request data
|
5
|
+
# and it communicates with interceptors.
|
6
|
+
class LHC::Request
|
7
|
+
|
8
|
+
TYPHOEUS_OPTIONS = [:params, :method, :body, :headers]
|
9
|
+
|
10
|
+
attr_accessor :response, :options, :raw
|
11
|
+
|
12
|
+
def initialize(options, self_executing = true)
|
13
|
+
self.options = options.deep_dup
|
14
|
+
use_configured_endpoint!
|
15
|
+
generate_url_from_template!
|
16
|
+
self.iprocessor = LHC::InterceptorProcessor.new(self)
|
17
|
+
self.raw = create_request
|
18
|
+
return unless self_executing
|
19
|
+
iprocessor.intercept(:before_request, self)
|
20
|
+
raw.run if !response
|
21
|
+
end
|
22
|
+
|
23
|
+
def url
|
24
|
+
raw.base_url || options[:url]
|
25
|
+
end
|
26
|
+
|
27
|
+
def method
|
28
|
+
(raw.options[:method] || options[:method] || :get).to_sym
|
29
|
+
end
|
30
|
+
|
31
|
+
def headers
|
32
|
+
raw.options.fetch(:headers, nil) || raw.options[:headers] = {}
|
33
|
+
end
|
34
|
+
|
35
|
+
def params
|
36
|
+
raw.options.fetch(:params, nil) || raw.options[:params] = {}
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
attr_accessor :iprocessor
|
42
|
+
|
43
|
+
def create_request
|
44
|
+
request = Typhoeus::Request.new(options[:url], typhoeusize(options))
|
45
|
+
request.on_headers do
|
46
|
+
iprocessor.intercept(:after_request, self)
|
47
|
+
iprocessor.intercept(:before_response, self)
|
48
|
+
end
|
49
|
+
request.on_complete { |response| on_complete(response) }
|
50
|
+
request
|
51
|
+
end
|
52
|
+
|
53
|
+
def typhoeusize(options)
|
54
|
+
options = options.deep_dup
|
55
|
+
easy = Ethon::Easy.new
|
56
|
+
options.delete(:url)
|
57
|
+
options.each do |key, v|
|
58
|
+
next if TYPHOEUS_OPTIONS.include? key
|
59
|
+
method = "#{key}="
|
60
|
+
options.delete key unless easy.respond_to?(method)
|
61
|
+
end
|
62
|
+
options
|
63
|
+
end
|
64
|
+
|
65
|
+
# Get configured endpoint and use it for doing the request.
|
66
|
+
# Explicit request options are overriding configured options.
|
67
|
+
def use_configured_endpoint!
|
68
|
+
return unless (endpoint = LHC.config.endpoints[options[:url]])
|
69
|
+
endpoint.options.deep_merge!(options)
|
70
|
+
options.deep_merge!(endpoint.options)
|
71
|
+
options[:url] = endpoint.url
|
72
|
+
end
|
73
|
+
|
74
|
+
# Generates URL from a URL template
|
75
|
+
def generate_url_from_template!
|
76
|
+
endpoint = LHC::Endpoint.new(options[:url])
|
77
|
+
options[:url] = endpoint.compile(options[:params])
|
78
|
+
endpoint.remove_interpolated_params!(options[:params])
|
79
|
+
end
|
80
|
+
|
81
|
+
def on_complete(response)
|
82
|
+
self.response ||= LHC::Response.new(response, self)
|
83
|
+
iprocessor.intercept(:after_response, self.response)
|
84
|
+
throw_error unless self.response.success?
|
85
|
+
end
|
86
|
+
|
87
|
+
def throw_error
|
88
|
+
error = LHC::Error.find(response)
|
89
|
+
fail error.new(error, response)
|
90
|
+
end
|
91
|
+
end
|