class Rack::LazyConditionalGet

This middleware is like Rack::ConditionalGet except that it does not have to go down the rack stack and build the resource to check the modification date or the ETag.

Instead it makes the assumption that only non-reading requests can potentially change the content, meaning any request which is not GET or HEAD. Each time you make one of these request, the date is cached and any resource is considered identical until the next non-reading request.

Basically you use it this way:

“` ruby use Rack::LazyConditionalGet “`

Although if you have multiple instances, it is better to use something like memcached. An argument can be passed to give the cache object. By default it is just a Hash. But it can take other objects, including objects which respond to `:get` and `:set`. Here is how you would use it with Dalli.

“` Ruby dalli_client = Dalli::Client.new use Rack::LazyConditionalGet, dalli_client “`

By default, the middleware only delegates to Rack::ConditionalGet to avoid any unwanted behaviour. You have to set a header to any resource which you want to be cached. And it will be cached until the next “potential update” of your site, that is whenever the next POST/PUT/PATCH/DELETE request is received.

The header is `Rack-Lazy-Conditional-Get`. You have to set it to 'yes' if you want the middleware to set `Last-Modified` for you.

Bear in mind that if you set `Last-Modified` as well, the middleware will not change it.

Regarding the POST/PUT/PATCH/DELETE… requests, they will always reset your global modification date. But if you have one of these request and you know for sure that it does not modify the cached content, you can set the `Rack-Lazy-Conditional-Get` on response to `skip`. This will not update the global modification date.

NOTE: This will not work properly in a multi-threaded environment with default cache object. A provided cache object should ensure thread-safety of the `get`/`set`/`[]`/`=` methods.

Constants

KEY
READ_METHODS

Public Class Methods

new(*) click to toggle source
Calls superclass method
   # File lib/rack/contrib/lazy_conditional_get.rb
58 def self.new(*)
59   # This code automatically uses `Rack::ConditionalGet` before
60   # our middleware. It is equivalent to:
61   #
62   # ``` ruby
63   # use Rack::ConditionalGet
64   # use Rack::LazyConditionalGet
65   # ```
66   ::Rack::ConditionalGet.new(super)
67 end
new(app, cache={}) click to toggle source
   # File lib/rack/contrib/lazy_conditional_get.rb
69 def initialize app, cache={}
70   @app = app
71   @cache = cache
72   update_cache
73 end

Public Instance Methods

call(env) click to toggle source
   # File lib/rack/contrib/lazy_conditional_get.rb
75 def call env
76   if reading? env and fresh? env
77     return [304, {'Last-Modified' => env['HTTP_IF_MODIFIED_SINCE']}, []]
78   end
79 
80   status, headers, body = @app.call env
81   headers = Utils::HeaderHash.new(headers)
82 
83   update_cache unless (reading?(env) or skipping?(headers))
84   headers['Last-Modified'] = cached_value if stampable? headers
85   [status, headers, body]
86 end

Private Instance Methods

cached_value() click to toggle source
    # File lib/rack/contrib/lazy_conditional_get.rb
115 def cached_value
116   @cache.respond_to?(:get) ? @cache.get(KEY) : @cache[KEY]
117 end
fresh?(env) click to toggle source
   # File lib/rack/contrib/lazy_conditional_get.rb
90 def fresh? env
91   env['HTTP_IF_MODIFIED_SINCE'] == cached_value
92 end
reading?(env) click to toggle source
   # File lib/rack/contrib/lazy_conditional_get.rb
94 def reading? env
95   READ_METHODS.include?(env['REQUEST_METHOD'])
96 end
skipping?(headers) click to toggle source
    # File lib/rack/contrib/lazy_conditional_get.rb
 98 def skipping? headers
 99   headers['Rack-Lazy-Conditional-Get'] == 'skip'
100 end
stampable?(headers) click to toggle source
    # File lib/rack/contrib/lazy_conditional_get.rb
102 def stampable? headers
103   !headers.has_key?('Last-Modified') and headers['Rack-Lazy-Conditional-Get'] == 'yes'
104 end
update_cache() click to toggle source
    # File lib/rack/contrib/lazy_conditional_get.rb
106 def update_cache
107   stamp = Time.now.httpdate
108   if @cache.respond_to?(:set)
109     @cache.set(KEY,stamp)
110   else
111     @cache[KEY] = stamp
112   end
113 end