class RestCore::Cache

Public Class Methods

members() click to toggle source
# File lib/rest-core/middleware/cache.rb, line 7
def self.members; [:cache, :expires_in]; end
new(app, cache, expires_in, &block) click to toggle source
Calls superclass method
# File lib/rest-core/middleware/cache.rb, line 10
def initialize app, cache, expires_in, &block
  super(&block)
  @app, @cache, @expires_in = app, cache, expires_in
end

Public Instance Methods

app_call(env) { |if (res || []).empty? cache_for(res) else res end| ... } click to toggle source
# File lib/rest-core/middleware/cache.rb, line 28
def app_call env
  app.call(env) do |res|
    yield(if (res[FAIL] || []).empty?
            cache_for(res)
          else
            res
          end)
  end
end
cache_get(env, &k) click to toggle source
# File lib/rest-core/middleware/cache.rb, line 43
def cache_get env, &k
  return unless cache(env)
  return unless cache_for?(env)

  uri = request_uri(env)
  start_time = Time.now
  return unless data = cache(env)[cache_key(env)]
  res = log(env.merge(REQUEST_URI => uri),
            Event::CacheHit.new(Time.now - start_time, uri))
  data_extract(data, res, k)
end
cache_key(env) click to toggle source
# File lib/rest-core/middleware/cache.rb, line 38
def cache_key env
  "rest-core:cache:#{Digest::MD5.hexdigest(env['cache.key'] ||
                                           cache_key_raw(env))}"
end
call(env, &k) click to toggle source
# File lib/rest-core/middleware/cache.rb, line 15
def call env, &k
  e = if env['cache.update']
        cache_clear(env)
      else
        env
      end

  cache_get(e){ |cached|
    e[TIMER].cancel if e[TIMER]
    k.call(cached)
  } || app_call(e, &k)
end

Private Instance Methods

cache_clear(env) click to toggle source
# File lib/rest-core/middleware/cache.rb, line 60
def cache_clear env
  return env unless cache(env)
  return env unless cache_for?(env)

  cache_store(env, :[]=, nil)
end
cache_for(res) click to toggle source
# File lib/rest-core/middleware/cache.rb, line 67
def cache_for res
  return res unless cache(res)
  return res unless cache_for?(res)

  if expires_in(res).kind_of?(Numeric) &&
     cache(res).respond_to?(:store)   &&
     cache(res).method(:store).arity == -3

    cache_store(res, :store, data_construct(res),
                               :expires_in => expires_in(res))
  else
    cache_store(res, :[]=  , data_construct(res))
  end
end
cache_for?(env) click to toggle source
# File lib/rest-core/middleware/cache.rb, line 112
def cache_for? env
  [:get, :head, :otpions].include?(env[REQUEST_METHOD]) &&
    !env[DRY] && !env[HIJACK]
end
cache_key_raw(env) click to toggle source
# File lib/rest-core/middleware/cache.rb, line 56
def cache_key_raw env
  "#{env[REQUEST_METHOD]}:#{request_uri(env)}:#{header_cache_key(env)}"
end
cache_store(res, msg, value, *args) click to toggle source
# File lib/rest-core/middleware/cache.rb, line 82
def cache_store res, msg, value, *args
  start_time = Time.now
  cache(res).send(msg, cache_key(res), value, *args)

  if value
    res
  else
    log(res,
      Event::CacheCleared.new(Time.now - start_time, request_uri(res)))
  end
end
data_construct(res) click to toggle source
# File lib/rest-core/middleware/cache.rb, line 94
def data_construct res
  "#{ res[RESPONSE_STATUS]}\n" \
  "#{(res[RESPONSE_HEADERS]||{}).map{|k,v|"#{k}: #{v}\n"}.join}\n\n" \
  "#{ res[RESPONSE_BODY]}"
end
data_extract(data, res, k) click to toggle source
# File lib/rest-core/middleware/cache.rb, line 100
def data_extract data, res, k
  _, status, headers, body =
    data.match(/\A(\d*)\n((?:[^\n]+\n)*)\n\n(.*)\Z/m).to_a

  result = res.merge(RESPONSE_STATUS => status.to_i,
                     RESPONSE_HEADERS =>
                       Hash[(headers||'').scan(/([^:]+): ([^\n]+)\n/)],
                     RESPONSE_BODY => body)

  result.merge(Promise.claim(result, &k).future_response)
end
header_cache_key(env) click to toggle source
# File lib/rest-core/middleware/cache.rb, line 117
def header_cache_key env
  env[REQUEST_HEADERS].sort.map{|(k,v)|"#{k}=#{v}"}.join('&')
end