Object
The MetaStore is responsible for storing meta information about a request/response pair keyed by the request’s URL.
The meta store keeps a list of request/response pairs for each canonical request URL. A request/response pair is a two element Array of the form:
[request, response]
The request element is a Hash of Rack environment keys. Only protocol keys (i.e., those that start with “HTTP_”) are stored. The response element is a Hash of cached HTTP response headers for the paired request.
The MetaStore class is abstract and should not be instanstiated directly. Concrete subclasses should implement the protected #, #, and # methods. Care has been taken to keep these low-level methods dumb and straight-forward to implement.
Generate a cache key for the request.
# File lib/rack/cache/metastore.rb, line 88 88: def cache_key(request) 89: keygen = request.env['rack-cache.cache_key'] || Key 90: keygen.call(request) 91: end
Invalidate all cache entries that match the request.
# File lib/rack/cache/metastore.rb, line 94 94: def invalidate(request, entity_store) 95: modified = false 96: key = cache_key(request) 97: entries = 98: read(key).map do |req, res| 99: response = restore_response(res) 100: if response.fresh? 101: response.expire! 102: modified = true 103: [req, persist_response(response)] 104: else 105: [req, res] 106: end 107: end 108: write key, entries if modified 109: end
Locate a cached response for the request provided. Returns a Rack::Cache::Response object if the cache hits or nil if no cache entry was found.
# File lib/rack/cache/metastore.rb, line 28 28: def lookup(request, entity_store) 29: key = cache_key(request) 30: entries = read(key) 31: 32: # bail out if we have nothing cached 33: return nil if entries.empty? 34: 35: # find a cached entry that matches the request. 36: env = request.env 37: match = entries.detect{|req,res| requests_match?(res['Vary'], env, req)} 38: return nil if match.nil? 39: 40: _, res = match 41: if body = entity_store.open(res['X-Content-Digest']) 42: restore_response(res, body) 43: else 44: # TODO the metastore referenced an entity that doesn't exist in 45: # the entitystore. we definitely want to return nil but we should 46: # also purge the entry from the meta-store when this is detected. 47: end 48: end
Write a cache entry to the store under the given key. Existing entries are read and any that match the response are removed. This method calls # with the new list of cache entries.
# File lib/rack/cache/metastore.rb, line 53 53: def store(request, response, entity_store) 54: key = cache_key(request) 55: stored_env = persist_request(request) 56: 57: # write the response body to the entity store if this is the 58: # original response. 59: if response.headers['X-Content-Digest'].nil? 60: if request.env['rack-cache.use_native_ttl'] && response.fresh? 61: digest, size = entity_store.write(response.body, response.ttl) 62: else 63: digest, size = entity_store.write(response.body) 64: end 65: response.headers['X-Content-Digest'] = digest 66: response.headers['Content-Length'] = size.to_s unless response.headers['Transfer-Encoding'] 67: response.body = entity_store.open(digest) 68: end 69: 70: # read existing cache entries, remove non-varying, and add this one to 71: # the list 72: vary = response.vary 73: entries = 74: read(key).reject do |env,res| 75: (vary == res['Vary']) && 76: requests_match?(vary, env, stored_env) 77: end 78: 79: headers = persist_response(response) 80: headers.delete 'Age' 81: 82: entries.unshift [stored_env, headers] 83: write key, entries 84: key 85: end
Remove all cached entries at the key specified. No error is raised when the key does not exist.
# File lib/rack/cache/metastore.rb, line 163 163: def purge(key) 164: raise NotImplemented 165: end
Locate all cached request/response pairs that match the specified URL key. The result must be an Array of all cached request/response pairs. An empty Array must be returned if nothing is cached for the specified key.
# File lib/rack/cache/metastore.rb, line 150 150: def read(key) 151: raise NotImplemented 152: end
Store an Array of request/response pairs for the given key. Concrete implementations should not attempt to filter or concatenate the list in any way.
# File lib/rack/cache/metastore.rb, line 157 157: def write(key, negotiations) 158: raise NotImplemented 159: end
Generate a SHA1 hex digest for the specified string. This is a simple utility method for meta store implementations.
# File lib/rack/cache/metastore.rb, line 170 170: def hexdigest(data) 171: Digest::SHA1.hexdigest(data) 172: end
Extract the environment Hash from request while making any necessary modifications in preparation for persistence. The Hash returned must be marshalable.
# File lib/rack/cache/metastore.rb, line 116 116: def persist_request(request) 117: env = request.env.dup 118: env.reject! { |key,val| key =~ /[^0-9A-Z_]/ || !val.respond_to?(:to_str) } 119: env 120: end
# File lib/rack/cache/metastore.rb, line 129 129: def persist_response(response) 130: hash = response.headers.to_hash 131: hash['X-Status'] = response.status.to_s 132: hash 133: end
Determine whether the two environment hashes are non-varying based on the vary response header value provided.
# File lib/rack/cache/metastore.rb, line 137 137: def requests_match?(vary, env1, env2) 138: return true if vary.nil? || vary == '' 139: vary.split(/[\s,]+/).all? do |header| 140: key = "HTTP_#{header.upcase.tr('-', '_')}" 141: env1[key] == env2[key] 142: end 143: end
Converts a stored response hash into a Response object. The caller is responsible for loading and passing the body if needed.
# File lib/rack/cache/metastore.rb, line 124 124: def restore_response(hash, body=nil) 125: status = hash.delete('X-Status').to_i 126: Rack::Cache::Response.new(status, hash, body) 127: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.