Class: Ahora::Middleware::LastModifiedCaching

Inherits:
Faraday::Middleware
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/ahora/middleware/last_modified_caching.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, cache = nil, options = {}) ⇒ LastModifiedCaching

Public: initialize the middleware.

cache - An object that responds to read, write and fetch (default: nil). options - An options Hash (default: {}):

:ignore_params - String name or Array names of query params
                 that should be ignored when forming the cache
                 key (default: []).
:cache_header  - String name of response header that should be
                 used to retrieve cache timestamp from.
                 Defaults to 'last-modified'
:expire_in     - Integer time to live value in seconds for a key.
                 Defaults to never expire.

Yields if no cache is given. The block should return a cache object.



23
24
25
26
27
28
# File 'lib/ahora/middleware/last_modified_caching.rb', line 23

def initialize(app, cache = nil, options = {})
  super(app)
  options, cache = cache, nil if cache.is_a? Hash and block_given?
  @cache = cache || yield
  @options = options
end

Instance Attribute Details

#cacheObject (readonly)

Returns the value of attribute cache.



4
5
6
# File 'lib/ahora/middleware/last_modified_caching.rb', line 4

def cache
  @cache
end

Instance Method Details

#cache_key(env) ⇒ Object



61
62
63
64
65
66
67
68
69
70
# File 'lib/ahora/middleware/last_modified_caching.rb', line 61

def cache_key(env)
  url = env[:url].dup
  if url.query && params_to_ignore.any?
    params = parse_query url.query
    params.reject! {|k,| params_to_ignore.include? k }
    url.query = build_query params
  end
  url.normalize!
  url.to_s
end

#call(env) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/ahora/middleware/last_modified_caching.rb', line 30

def call(env)
  if env[:method] == :get

    timestamp_key = cache_key(env) + ':timestamp'
    data_key      = cache_key(env) + ':response'

    if date = cache.read(timestamp_key)
      # WARN FakeWeb cannot test this
      env[:request_headers]['If-Modified-Since'] = Time.parse(date).httpdate
    end

    response = @app.call(env)

    if response.status == 304
      response = cache.read data_key
    elsif date = response.headers[@options[:cache_header] || 'Last-Modified']
      response.env[:response_headers]['X-Ahora-Cache-Key'] = fragment_cache_key(env, date)
      cache.write timestamp_key, date, :expire_in => @options[:expire_in]
      cache.write data_key, response, :expire_in => @options[:expire_in]
    end

    finalize_response(response, env)
  else
    @app.call(env)
  end
end

#finalize_response(response, env) ⇒ Object



76
77
78
79
80
81
82
83
84
85
# File 'lib/ahora/middleware/last_modified_caching.rb', line 76

def finalize_response(response, env)
  response = response.dup if response.frozen?
  env[:response] = response
  unless env[:response_headers]
    env.update response.env
    # FIXME: omg hax
    response.instance_variable_set('@env', env)
  end
  response
end

#fragment_cache_key(env, last_modified) ⇒ Object



57
58
59
# File 'lib/ahora/middleware/last_modified_caching.rb', line 57

def fragment_cache_key(env, last_modified)
  cache_key(env) + ":fragment_#{last_modified}"
end

#params_to_ignoreObject



72
73
74
# File 'lib/ahora/middleware/last_modified_caching.rb', line 72

def params_to_ignore
  @params_to_ignore ||= Array(@options[:ignore_params]).map { |p| p.to_s }
end