class Rack::StaticCache

The Rack::StaticCache middleware automatically adds, removes and modifies stuffs in response headers to facilitiate client and proxy caching for static files that minimizes http requests and improves overall load times for second time visitors.

Once a static content is stored in a client/proxy the only way to enforce the browser to fetch the latest content and ignore the cache is to rename the static file.

Alternatively, we can add a version number into the URL to the content to bypass the caches. Rack::StaticCache by default handles version numbers in the filename. As an example, and both reffers to the same image file

Another way to bypass the cache is adding the version number in a field-value pair in the URL query string. As an example, yoursite.com/images/test.png?v=1.0.0 In that case, set the option :versioning to false to avoid unnecessary regexp calculations.

It's better to keep the current version number in some config file and use it in every static content's URL. So each time we modify our static contents, we just have to change the version number to enforce the browser to fetch the latest content.

You can use Rack::Deflater along with Rack::StaticCache for further improvements in page loading time.

If you'd like to use a non-standard version identifier in your URLs, you can set the regex to remove with the `:version_regex` option. If you want to capture something after the regex (such as file extensions), you should capture that as `1`. All other captured subexpressions will be discarded. You may find the `?:` capture modifier helpful.

Examples:

use Rack::StaticCache, :urls => ["/images", "/css", "/js", "/documents*"], :root => "statics"
will serve all requests beginning with /images, /css or /js from the
directory "statics/images",  "statics/css",  "statics/js".
All the files from these directories will have modified headers to enable client/proxy caching,
except the files from the directory "documents". Append a * (star) at the end of the pattern
if you want to disable caching for any pattern . In that case, plain static contents will be served with
default headers.

use Rack::StaticCache, :urls => ["/images"], :duration => 2, :versioning => false
will serve all requests beginning with /images under the current directory (default for the option :root
is current directory). All the contents served will have cache expiration duration set to 2 years in headers
(default for :duration is 1 year), and StaticCache will not compute any versioning logics (default for
:versioning is true)

Public Class Methods

new(app, options={}) click to toggle source
   # File lib/rack/contrib/static_cache.rb
56 def initialize(app, options={})
57   @app = app
58   @urls = options[:urls]
59   @no_cache = {}
60   @urls.collect! do |url|
61     if url  =~ /\*$/
62       url_prefix = url.sub(/\*$/, '')
63       @no_cache[url_prefix] = 1
64       url_prefix
65     else
66       url
67     end
68   end
69   root = options[:root] || Dir.pwd
70   @file_server = Rack::File.new(root)
71   @cache_duration = options[:duration] || 1
72   @versioning_enabled = options.fetch(:versioning, true)
73   if @versioning_enabled
74     @version_regex = options.fetch(:version_regex, /-[\d.]+([.][a-zA-Z][\w]+)?$/)
75   end
76   @duration_in_seconds = self.duration_in_seconds
77 end

Public Instance Methods

call(env) click to toggle source
   # File lib/rack/contrib/static_cache.rb
79 def call(env)
80   path = env["PATH_INFO"]
81   url = @urls.detect{ |u| path.index(u) == 0 }
82   if url.nil?
83     @app.call(env)
84   else
85     if @versioning_enabled
86       path.sub!(@version_regex, '\1')
87     end
88 
89     status, headers, body = @file_server.call(env)
90     headers = Utils::HeaderHash.new(headers)
91 
92     if @no_cache[url].nil?
93       headers['Cache-Control'] ="max-age=#{@duration_in_seconds}, public"
94       headers['Expires'] = duration_in_words
95     end
96     headers['Date'] = Time.now.httpdate
97     [status, headers, body]
98   end
99 end
duration_in_seconds() click to toggle source
    # File lib/rack/contrib/static_cache.rb
105 def duration_in_seconds
106   (60 * 60 * 24 * 365 * @cache_duration).to_i
107 end
duration_in_words() click to toggle source
    # File lib/rack/contrib/static_cache.rb
101 def duration_in_words
102   (Time.now.utc + self.duration_in_seconds).httpdate
103 end