Created
May 18, 2009 12:23
-
-
Save nutrun/113441 to your computer and use it in GitHub Desktop.
Middleware for configuring HTTP cache policy headers in Rack based web applications.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Cache Headers | |
# Middleware for configuring HTTP cache policy headers in Rack based web applications. | |
# Apply cache headers to HTTP responses corresponding to requests that match defined | |
# URI patterns. | |
# | |
# Example usage: | |
# | |
# use Rack::CacheHeaders | |
# | |
# Rack::CacheHeaders.configure do |cache| | |
# cache.max_age(/^\/$/, 3600) | |
# cache.private(/^\/search$/) | |
# cache.pragma_no_cache(/^\/search$/) | |
# cache.expires(/^\/search$/, Time.now - 630720000) | |
# cache.expires(/^\/about\/.+$/, "00:00") | |
# end | |
module Rack | |
class CacheHeaders | |
def initialize(app) | |
@app = app | |
end | |
def call(env) | |
result = @app.call(env) | |
if path = Configuration[env['PATH_INFO']] | |
path.each do |policy| | |
header = policy.to_header | |
result[1][header.key] = header.value | |
end | |
end | |
result | |
end | |
def self.configure(&block) | |
yield Configuration | |
end | |
class Configuration | |
def self.max_age(path, duration) | |
(paths[path] ||= []) << MaxAge.new(duration) | |
end | |
def self.expires(path, date) | |
(paths[path] ||= []) << Expires.new(date) | |
end | |
def self.private(path) | |
(paths[path] ||= []) << Private.new | |
end | |
def self.pragma_no_cache(path) | |
(paths[path] ||= []) << PragmaNoCache.new | |
end | |
def self.[](key) | |
key = paths.keys.find { |e| e =~ key } | |
paths[key] if key | |
end | |
def self.paths | |
@paths ||= {} | |
end | |
end | |
class MaxAge | |
def initialize(duration) | |
@duration = duration | |
end | |
def to_header | |
Header.new("Cache-Control", "max-age=#{@duration}, must-revalidate") | |
end | |
end | |
class Expires | |
def initialize(date) | |
@date = date | |
end | |
def to_header | |
if @date.is_a?(Time) | |
Header.new("Expires", @date.httpdate) | |
else | |
d = Time.parse(@date) | |
d = d + (60*60*24) if d < Time.now | |
Header.new("Expires", d.httpdate) | |
end | |
end | |
end | |
class Private | |
def to_header | |
Header.new("Cache-Control", 'private') | |
end | |
end | |
class PragmaNoCache | |
def to_header | |
Header.new('Pragma', 'no-cache') | |
end | |
end | |
class Header < Struct.new(:key, :value);end | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment