Class: Rack::LazyConditionalGet

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/contrib/lazy_conditional_get.rb

Overview

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.

Constant Summary collapse

KEY =
'global_last_modified'.freeze
READ_METHODS =
['GET','HEAD']

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, cache = {}) ⇒ LazyConditionalGet

Returns a new instance of LazyConditionalGet.



63
64
65
66
67
# File 'lib/rack/contrib/lazy_conditional_get.rb', line 63

def initialize app, cache={}
  @app = app
  @cache = cache
  update_cache
end

Class Method Details

.newObject



52
53
54
55
56
57
58
59
60
61
# File 'lib/rack/contrib/lazy_conditional_get.rb', line 52

def self.new(*)
  # This code automatically uses `Rack::ConditionalGet` before
  # our middleware. It is equivalent to:
  #
  # ``` ruby
  # use Rack::ConditionalGet
  # use Rack::LazyConditionalGet
  # ```
  ::Rack::ConditionalGet.new(super)
end

Instance Method Details

#call(env) ⇒ Object



69
70
71
72
73
74
75
76
77
# File 'lib/rack/contrib/lazy_conditional_get.rb', line 69

def call env
  if reading? env and fresh? env
    return [304, {'Last-Modified' => env['HTTP_IF_MODIFIED_SINCE']}, []]
  end
  status, headers, body = @app.call env
  update_cache unless (reading?(env) or skipping?(headers))
  headers['Last-Modified'] = cached_value if stampable? headers
  [status, headers, body]
end