class Grifter::HTTPService

Constants

RequestLogSeperator

Attributes

config[R]
conn[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/grifter/http_service.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 '#{@name}' with:\n\t#{@config.inspect}"

  #@conn = Net::HTTP.new(@config[:hostname], @config[:port])
  #@conn.use_ssl = @config[:ssl]
  @conn = 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 grifter service '#{@name}'"
end

Public Instance Methods

delete(path, options={}) click to toggle source
# File lib/grifter/http_service.rb, line 193
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/grifter/http_service.rb, line 79
def do_request method, path, obj=nil, options={}

  #grifter clients pass in path possibly including query params.
  #Faraday needs the query and path seperately.
  parsed = URI.parse make_path(path)
  #faraday needs the request params as a hash.
  #this turns out to be non-trivial
  query_hash = if parsed.query
                 cgi_hash = CGI.parse(parsed.query)
                 #make to account for one param having multiple values
                 cgi_hash.inject({}) { |h,(k,v)| h[k] = v[1] ? v : v.first; h }
               else
                 nil
               end

  req_headers = make_headers(options)

  body = if options[:form]
    URI.encode_www_form obj
  else
    jsonify(obj)
  end

  #log the request
  logger.debug [
    "Doing request: #{@name}: #{method.to_s.upcase} #{path}",
    @log_headers ? ["Request Headers:",
    req_headers.map{ |k, v| "#{k}: #{v.inspect}" }] : nil,
    @log_bodies ? ["Request Body:", body] : nil,
  ].flatten.compact.join("\n")

  #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: path, request_body: body, request_headers: req_headers }
  ActiveSupport::Notifications.instrument(Grifter::Instrumentation::InstrumentationQueueName, metrics_obj) do
    response = @conn.run_request(method, nil, nil, nil) do |req|
      req.path = parsed.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: path,
    headers: req_headers,
    body: body,
  }
  @last_response = response

  response_obj = objectify response.body
  if response.headers['content-type'] =~ /json/
    logger.debug [
      "Response Details:",
      @log_headers ? ["Response Headers:",
                      response.headers.map { |k, v| "#{k}: #{v.inspect}" }] : nil,
      @log_bodies ? [ "Response Body:", jsonify(response_obj)] : nil,
      ''
    ].flatten.compact.join("\n")
  end

  raise RequestException.new(nil, response) unless response.status >= 200 and response.status < 300

  return response_obj
end
get(path, options={}) click to toggle source
# File lib/grifter/http_service.rb, line 181
def get path, options={}
  do_request :get, path, nil, options
end
head(path, options={}) click to toggle source
# File lib/grifter/http_service.rb, line 185
def head path, options={}
  do_request :head, path, nil, options
end
in_parallel(&blk) click to toggle source
# File lib/grifter/http_service.rb, line 150
def in_parallel &blk
  @conn.headers = @headers
  @conn.in_parallel &blk
end
make_headers(options) click to toggle source
# File lib/grifter/http_service.rb, line 165
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, base_uri=nil) click to toggle source

add base uri to request

# File lib/grifter/http_service.rb, line 156
def make_path path_suffix, base_uri=nil
  base_uri_to_use = base_uri ? base_uri : @base_uri
  if base_uri_to_use
    base_uri_to_use + path_suffix
  else
    path_suffix
  end
end
options(path, options={}) click to toggle source
# File lib/grifter/http_service.rb, line 189
def options path, options={}
  do_request :options, path, nil, options
end
patch(path, obj, options={}) click to toggle source
# File lib/grifter/http_service.rb, line 205
def patch path, obj, options={}
  do_request :patch, path, obj, options
end
post(path, obj, options={}) click to toggle source
# File lib/grifter/http_service.rb, line 197
def post path, obj, options={}
  do_request :post, path, obj, options
end
post_form(path, params, options={}) click to toggle source
# File lib/grifter/http_service.rb, line 209
def post_form path, params, options={}
  do_request :post, path, params, options.merge(form: true)
  #request_obj = Net::HTTP::Post.new(*req_args(path, options))
  #request_obj.set_form_data params
  #do_request request_obj, options
end
put(path, obj, options={}) click to toggle source
# File lib/grifter/http_service.rb, line 201
def put path, obj, options={}
  do_request :put, path, obj, options
end
req_args(path, options) click to toggle source
# File lib/grifter/http_service.rb, line 177
def req_args path, options
  [make_path(path, options[:base_uri]), make_headers(options)]
end
stubs(&blk) click to toggle source
# File lib/grifter/http_service.rb, line 56
def stubs &blk
  stubs = Faraday::Adapter::Test::Stubs.new
  @conn = Faraday.new @config[:faraday_url] do |conn_builder|
    conn_builder.adapter :test, stubs
  end
  stubs
end