class APIConsumer

Constants

DEFAULT_REQUEST_OPTS

Public Class Methods

cache() click to toggle source
# File lib/api_consumer.rb, line 172
def cache
  @cache ||= UberCache.new(settings[:cache_prefix], settings[:memcache_hosts])
end
connection(connection_flag = :normal) click to toggle source
# File lib/api_consumer.rb, line 150
def connection(connection_flag = :normal)
  @connections ||= {}
  return @connections[connection_flag] if @connections[connection_flag]
  @connections[connection_flag] = create_connection
end
create_connection(debug = false) click to toggle source
# File lib/api_consumer.rb, line 156
def create_connection(debug = false)
  if @uri.nil? || @uri.port.nil?
    log.info "CONNECTING TO: #{settings[:url]}"
    @uri = URI.parse("#{settings[:url]}/")
  end
  http = Net::HTTP.new(@uri.host, @uri.port)
  if settings[:ssl] == true
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  end
  http.set_debug_output $stderr if debug
  http.open_timeout = 7
  http.read_timeout = 15
  http
end
do_request(path, conn, opts = {}, &blk) click to toggle source
# File lib/api_consumer.rb, line 76
def do_request(path, conn, opts = {}, &blk)
  if(opts[:verbose])
    log.debug("Sending request to: #{conn.address}#{':' + conn.port.to_s if conn.port}#{path}")
  end
  if opts[:key] # cache if key sent
    read_val = nil
    return read_val if !opts[:reload] && read_val = cache.obj_read(opts[:key])
    opts[:ttl] ||= settings[:ttl] || DEFAULT_REQUEST_OPTS[:ttl]
  end
  opts[:headers] = DEFAULT_REQUEST_OPTS[:headers].merge(opts[:headers] || {})
  opts[:method] = opts[:method] || DEFAULT_REQUEST_OPTS[:method]

  req = if( opts[:method] == :get)
    Net::HTTP::Get.new(path)
  elsif( opts[:method] == :post)
    Net::HTTP::Post.new(path)
  elsif( opts[:method] == :delete)
    Net::HTTP::Delete.new(path)
  elsif( opts[:method] == :put)
    Net::HTTP::Put.new(path)
  else
    log.error "Unhandled HTTP method => (#{opts[:method]})"
  end
  opts[:headers].each { |k,v| req[k] = v }
  settings[:headers].each { |k,v| req[k] = v } if settings[:headers]
  req.basic_auth settings[:api_user], settings[:api_password] if settings[:api_user] && settings[:api_password]
  req["connection"] = 'keep-alive' if settings[:keep_alive]
  req.body = opts[:body] if opts[:body]

  response = nil
  begin
    log.debug "CONN:" + conn.inspect
    log.debug "REQ:" + req.inspect
    response = conn.request(req)
    if( settings[:type] == "json")
      results = JSON.parse(response.body)
      good_codes = [200, 201, 202] 
      good_codes += settings[:accept_codes].map(&:to_i) if settings[:accept_codes]
      if !good_codes.include?(response.code.to_i)
        results = error_code(response.code, opts[:errors], results)
      end
      results = blk.call(results) if blk
      begin
        cache.obj_write(opts[:key], results, :ttl => opts[:ttl]) if opts[:key]
      rescue Exception => exception
        # write error messages to the log file but ignore exceptions in writing data to cache
        log.error exception.message
        log.error exception.backtrace
      end
      return results
    elsif( settings[:type] == "rss")
      rss = Nokogiri::XML(response.body)
      return rss.xpath("//item").map{ |i|
        { 'title' => i.xpath('title').inner_text,
          'link' => i.xpath('link').inner_text,
          'description' => i.xpath('description').inner_text
        }
      }
    elsif( settings[:type] == "xml")
      return Nori.new(nori_settings).parse(response.body)
    end
  rescue Exception => exception
    log.error exception.message
    log.error exception.backtrace
    if( settings[:type] == "json")
      return error_code(response ? response.code : "NO CODE" , opts[:errors], response.body)
    end
  end
  data = response.body
  data = blk.call(data) if blk
  cache.obj_write(opts[:key], data, :ttl => opts[:ttl]) if opts[:key]
  return data
end
inherited(subclass) click to toggle source
Calls superclass method
# File lib/api_consumer.rb, line 13
def inherited(subclass)
  configs = YAML.load_file("config/#{snake_case(subclass)}.yml")
  configs[snake_case(subclass)].each{ |k,v| subclass.set(k.to_sym, v) }
  subclass.set_logger(Logger.new(subclass.settings[:log_file] || "./log/#{snake_case(subclass)}_api.log"), subclass.settings[:log_level])
  super
end
log() click to toggle source
# File lib/api_consumer.rb, line 25
def log
  @logger
end
memcache?() click to toggle source
# File lib/api_consumer.rb, line 51
def memcache?
  settings[:use_memcache]
end
memcache_hosts() click to toggle source
# File lib/api_consumer.rb, line 55
def memcache_hosts
  settings[:memcache_hosts]
end
set(key, val) click to toggle source
# File lib/api_consumer.rb, line 59
def set(key, val)
  settings[key] = val
end
set_log_level(level=nil) click to toggle source
# File lib/api_consumer.rb, line 29
def set_log_level(level=nil)
  if level.nil?
    level = if([nil, "development", "test"].include?(ENV['RACK_ENV']))
      :info
    else
      :warn
    end
  end
  @logger.level = case level.to_sym
  when :debug
    Logger::DEBUG
  when :info
    Logger::INFO
  when :error
    Logger::ERROR
  when :fatal
    Logger::FATAL
  else #warn
    Logger::WARN
  end
end
set_logger(logger, level=nil) click to toggle source
# File lib/api_consumer.rb, line 20
def set_logger(logger, level=nil)
  @logger = logger.nil? ? Logger.new(STDERR) : logger
  set_log_level(level)
end
settings() click to toggle source
# File lib/api_consumer.rb, line 63
def settings
  @settings ||= {}
end

Private Class Methods

error_code(code, errors = nil, response = nil) click to toggle source
# File lib/api_consumer.rb, line 193
def error_code(code, errors = nil, response = nil)
  ret_val = {:error => true, :message => (errors && errors[code.to_s] ? errors[code.to_s] : "API error: #{code}" )}
  ret_val[:response] = response if response
  return ret_val
end
nori_settings() click to toggle source
# File lib/api_consumer.rb, line 185
def nori_settings
  nori_sets = {}
  if settings[:nori_settings].kind_of?(Hash)
    settings[:nori_settings].each{|k, v| nori_sets[k.to_sym] = v}
  end
  return nori_sets
end
snake_case(camel_cased_word) click to toggle source
# File lib/api_consumer.rb, line 177
def snake_case(camel_cased_word)
  camel_cased_word.to_s.gsub(/::/, '_').
  gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
  gsub(/([a-z\d])([A-Z])/,'\1_\2').
  tr("-", "_").
  downcase
end