class Heroku::Conn

Constants

APIRequest

Public Class Methods

cache() click to toggle source
# File lib/heroku/conn.rb, line 15
def self.cache
  @cache ||= Heroku::Conn::Cache.new
end
method_missing(method, end_point, opts = {}) click to toggle source
# File lib/heroku/conn.rb, line 19
def self.method_missing(method, end_point, opts = {})
  _Request = Net::HTTP.const_get(method.capitalize)

  req      = _Request.new(end_point, headers(opts))
  req.body = opts[:body]
  api_req  = APIRequest[method, end_point]

  Heroku::Properties.logger.debug("[Conn] Attempting #{method.upcase} #{end_point} ...")

  check_response(api_req, opts[:r_type], @https.request(req))
end

Private Class Methods

check_response(api_req, r_type, res) click to toggle source
# File lib/heroku/conn.rb, line 33
def self.check_response(api_req, r_type, res)
  Heroku::Properties.logger.debug("[Conn] Received #{res.code} for #{r_type} at #{api_req.end_point}")

  case res
  when Net::HTTPOK,
       Net::HTTPCreated
    cache.put(
      r_type, res["ETag"],
      parse_body(res)
    )
  when Net::HTTPPartialContent
    cache.put(
      r_type, res["ETag"],
      gather_partial_content(api_req, res)
    )
  when Net::HTTPNotModified then cache.fetch(r_type, res["ETag"])
  when Net::HTTPSuccess     then [res["ETag"], parse_body(res)]
  else                           raise_exception(res)
  end
end
decompress(res) click to toggle source
# File lib/heroku/conn.rb, line 96
def self.decompress(res)
  case res["content-encoding"]
  when 'gzip'
    Zlib::GzipReader.new(
      StringIO.new(res.body),
      encoding: "ASCII-8BIT"
    ).read
  when 'deflate'
    Zlib::Inflate.inflate(res.body)
  else
    res.body
  end
end
headers(opts = {}) click to toggle source
# File lib/heroku/conn.rb, line 80
def self.headers(opts = {})
  {
    "Accept"        => 'application/vnd.heroku+json; version=3',
    "Content-Type"  => 'application/json;charset=utf-8',
    "Authorization" => Heroku::Properties.auth_token,
    "User-Agent"    => Heroku::Properties::USER_AGENT
  }.merge({}.tap do |header|
    header["If-None-Match"] = opts[:etag]  if opts[:etag]
    header["Range"]         = opts[:range] if opts[:range]
  end)
end
parse_body(res) click to toggle source
# File lib/heroku/conn.rb, line 92
def self.parse_body(res)
  JSON.parse(decompress(res))
end
raise_exception(res) click to toggle source
# File lib/heroku/conn.rb, line 68
def self.raise_exception(res)
  Heroku::Properties.logger.error("[Conn response] #{res.body.inspect}")
  Heroku::Properties.logger.error("[Conn] Uh oh, something went wrong with request #{res["Request-Id"]}.")
  raise res.class::EXCEPTION_TYPE.new(status(res.code), nil)
end
status(code) click to toggle source
# File lib/heroku/conn.rb, line 74
def self.status(code)
  Hash[Net::HTTPResponse::CODE_TO_OBJ.map { |k, v| [k, v.to_s] }]
    .merge({ "429" => "Net::HTTPTooManyRequests" }) # Ruby 1.9.3 shiv
    .fetch(code, "Net::HTTPUnknownError")
end

Private Instance Methods

gather_partial_content(api_req, res) click to toggle source
# File lib/heroku/conn.rb, line 54
def gather_partial_content(api_req, res)
  Heroku::Properties.logger.info("[Conn] Gathering Partial Content.")

  list_head = parse_body(res)
  etag, list_tail =
    self.send(
      api_req.method,
      api_req.end_point,
      range: res["Next-Range"]
    )

  list_tail.unshift(*list_head)
end