class Hatt::HTTP
Attributes
config[R]
faraday_connection[R]
headers[RW]
http[R]
allow stubbing http if we are testing
last_request[R]
this is useful for testing apis, and other times you want to interrogate the http details of a response
last_response[R]
this is useful for testing apis, and other times you want to interrogate the http details of a response
name[R]
Public Class Methods
new(config)
click to toggle source
# File lib/hatt/http.rb, line 16 def initialize(config) @config = config @name = @config[:name] @base_uri = @config[:base_uri] @log_headers = @config.fetch(:log_headers, true) @log_bodies = @config.fetch(:log_bodies, true) logger.debug "Configuring service:\n#{@config.to_hash.to_yaml}\n" @faraday_connection = Faraday.new @config[:faraday_url] do |conn_builder| # do our own logging # conn_builder.response logger: logger # conn_builder.adapter Faraday.default_adapter # make requests with Net::HTTP conn_builder.adapter @config.fetch(:adapter, :typhoeus).intern conn_builder.ssl[:verify] = false if @config[:ignore_ssl_cert] # defaulting this to flat adapter avoids issues when duplicating parameters conn_builder.options[:params_encoder] = Faraday.const_get(@config.fetch(:params_encoder, 'FlatParamsEncoder')) # this nonsense dont work?! https://github.com/lostisland/faraday_middleware/issues/76 # conn_builder.use :instrumentation end @headers = { 'accept' => 'application/json', 'content-type' => 'application/json' } if @config[:default_headers] logger.debug 'Default headers configured: ' + @config[:default_headers].inspect @config[:default_headers].each_pair do |k, v| @headers[k.to_s] = v.to_s end end @default_timeout = @config.fetch(:timeout, 10) logger.info "Initialized hatt service '#{@name}'" end
Public Instance Methods
delete(path, options = {})
click to toggle source
# File lib/hatt/http.rb, line 148 def delete(path, options = {}) do_request :delete, path, nil, options end
do_request(method, path, obj = nil, options = {})
click to toggle source
do_request
performs the actual request, and does associated logging options can include:
-
:timeout, which specifies num secs the request should timeout in (this turns out to be kind of annoying to implement)
# File lib/hatt/http.rb, line 79 def do_request(method, path, obj = nil, options = {}) # hatt clients pass in path possibly including query params. # Faraday needs the query and path seperately. parsed_uri = URI.parse make_path(path) # faraday needs the request params as a hash. # this turns out to be non-trivial query_hash = if parsed_uri.query cgi_hash = CGI.parse(parsed_uri.query) # this next line accounts for one param having multiple values cgi_hash.each_with_object({}) { |(k, v), h| h[k] = v[1] ? v : v.first; } end req_headers = make_headers(options) body = if options[:form] URI.encode_www_form obj else jsonify(obj) end log_request(method, parsed_uri, query_hash, req_headers, body) # doing it this way avoids problem with OPTIONS method: https://github.com/lostisland/faraday/issues/305 response = nil metrics_obj = { method: method, service: @name, path: parsed_uri.path } ActiveSupport::Notifications.instrument('request.hatt', metrics_obj) do response = @faraday_connection.run_request(method, nil, nil, nil) do |req| req.path = parsed_uri.path req.params = metrics_obj[:params] = query_hash if query_hash req.headers = req_headers req.body = body req.options[:timeout] = options.fetch(:timeout, @default_timeout) end metrics_obj[:response] = response end logger.info "Request status: (#{response.status}) #{@name}: #{method.to_s.upcase} #{path}" @last_request = { method: method, path: parsed_uri.path, query: parsed_uri.query, headers: req_headers, body: body } @last_response = response response_obj = objectify response.body log_response(response, response_obj) raise RequestException.new(nil, response) unless response.status >= 200 && response.status < 300 response_obj end
get(path, options = {})
click to toggle source
# File lib/hatt/http.rb, line 136 def get(path, options = {}) do_request :get, path, nil, options end
head(path, options = {})
click to toggle source
# File lib/hatt/http.rb, line 140 def head(path, options = {}) do_request :head, path, nil, options end
in_parallel(&blk)
click to toggle source
# File lib/hatt/http.rb, line 70 def in_parallel(&blk) @faraday_connection.headers = @headers @faraday_connection.in_parallel(&blk) end
last_response_status()
click to toggle source
convenience method for accessing the last response status code
# File lib/hatt/http.rb, line 169 def last_response_status @last_response.status end
options(path, options = {})
click to toggle source
# File lib/hatt/http.rb, line 144 def options(path, options = {}) do_request :options, path, nil, options end
patch(path, obj, options = {})
click to toggle source
# File lib/hatt/http.rb, line 160 def patch(path, obj, options = {}) do_request :patch, path, obj, options end
post(path, obj, options = {})
click to toggle source
# File lib/hatt/http.rb, line 152 def post(path, obj, options = {}) do_request :post, path, obj, options end
post_form(path, params, options = {})
click to toggle source
# File lib/hatt/http.rb, line 164 def post_form(path, params, options = {}) do_request :post, path, params, options.merge(form: true) end
put(path, obj, options = {})
click to toggle source
# File lib/hatt/http.rb, line 156 def put(path, obj, options = {}) do_request :put, path, obj, options end
stubs()
click to toggle source
# File lib/hatt/http.rb, line 53 def stubs stubs = Faraday::Adapter::Test::Stubs.new @faraday_connection = Faraday.new @config[:faraday_url] do |conn_builder| conn_builder.adapter :test, stubs end stubs end
Private Instance Methods
log_request(method, parsed_uri, query_hash={}, headers, body)
click to toggle source
# File lib/hatt/http.rb, line 196 def log_request(method, parsed_uri, query_hash={}, headers, body) # log the request logger.debug [ "Doing request: #{@name}: #{method.to_s.upcase} #{parsed_uri.path}?#{query_hash.is_a?(Hash) ? URI.encode_www_form(query_hash) : ''}", @log_headers ? ['Request Headers:', headers.map { |k, v| "#{k}: #{v.inspect}" }] : nil, @log_bodies ? ['Request Body:', body] : nil ].flatten.compact.join("\n") end
log_response(response, response_obj)
click to toggle source
# File lib/hatt/http.rb, line 206 def log_response(response, response_obj) log_messages = [ 'Response Details:', @log_headers ? ['Response Headers:', response.headers.map { |k, v| "#{k}: #{v.inspect}" }] : nil ] if response.headers['content-type'] =~ /json/ log_messages += [ @log_bodies ? ['Response Body:', jsonify(response_obj)] : nil, '' ] end logger.debug log_messages.flatten.compact.join("\n") end
make_headers(options)
click to toggle source
# File lib/hatt/http.rb, line 184 def make_headers(options) headers = if options[:additional_headers] @headers.merge options[:additional_headers] elsif options[:headers] options[:headers] else @headers.clone end headers['content-type'] = 'application/x-www-form-urlencoded' if options[:form] headers end
make_path(path_suffix)
click to toggle source
add base uri to request
# File lib/hatt/http.rb, line 176 def make_path(path_suffix) if @base_uri @base_uri + path_suffix else path_suffix end end