class Rack::Cache::CacheControl
Directives that do not have values are set to true
.
Parses a cache-control header and exposes the directives as a Hash.
def initialize(value=nil)
def initialize(value=nil) parse(value) end
def max_age
that the client is willing to accept a response whose age is no
When the max-age directive is included in the request, it indicates
non-cacheable in order to retain compatibility with HTTP/1.0 servers.
cache-control header field, it SHOULD consider the response to be
cache receives such a response, and the response does not include a
to the cache-control response directive "no-cache". If an HTTP/1.1
is less than or equal to the response Date value as being equivalent
Many HTTP/1.0 cache implementations will treat an expires value that
expiration times, perhaps due to desynchronized clocks.
useful if certain HTTP/1.0 caches improperly calculate ages or
an HTTP/1.1 (or later) cache than to an HTTP/1.0 cache. This might be
server to provide, for a given response, a longer expiration time to
if the expires header is more restrictive. This rule allows an origin
directive, the max-age directive overrides the expires header, even
If a response includes both an expires header and a max-age
restrictive cache directive is also present.
response is cacheable (i.e., "public") unless some other, more
resource. The max-age directive on a response implies that the
value given (in seconds) at the time of a new request for that
the response is stale if its current age is greater than the age
the max-age cache-control directive is present in a cached response,
it MAY be specified using the max-age directive in a response. When
server using the expires header (see section 14.21). Alternatively,
The expiration time of an entity MAY be specified by the origin
def max_age self['max-age'].to_i if key?('max-age') end
def must_revalidate?
violates this directive, and MUST NOT automatically provide an
transaction. Recipients MUST NOT take any automated action that
incorrect operation, such as a silently unexecuted financial
failure to revalidate a request on the entity could result in
Servers SHOULD send the must-revalidate directive if and only if
reason, it MUST generate a 504 (Gateway Timeout) response.
particular, if the cache cannot reach the origin server for any
HTTP/1.1 cache MUST obey the must-revalidate directive; in
operation for certain protocol features. In all circumstances an
The must-revalidate directive is necessary to support reliable
value, the cached response is stale.)
time, if, based solely on the origin server's expires or max-age
server. (I.e., the cache MUST do an end-to-end revalidation every
subsequent request without first revalidating it with the origin
MUST NOT use the entry after it becomes stale to respond to a
directive is present in a response received by a cache, that cache
of a cache entry on any subsequent use. When the must-revalidate
includes a mechanism for the origin server to require revalidation
stale directive (which has a similar effect), the protocol also
expiration time, and because a client request MAY include a max-
Because a cache MAY be configured to ignore a server's specified
def must_revalidate? self['must-revalidate'] end
def no_cache?
directive on responses. When the client specifies no-cache, it causes
response. This has quite different semantics compared to the no-cache
When set in a request, the server MUST NOT use a cached copy for its
making a conditional GET request with the origin server.
stored by the cache, only that the cache cannot serve it without first
Note that this does not necessary imply that the response may not be
that have been configured to return stale responses to client requests.
server. This allows an origin server to prevent caching even by caches
subsequent request without successful revalidation with the origin
When set in a response, a cache MUST NOT use the response to satisfy a
def no_cache? self['no-cache'] end
def no_store?
obey this directive, and communications networks might be
particular, malicious or compromised caches might not recognize or
way a reliable or sufficient mechanism for ensuring privacy. In
improve privacy in some cases, we caution that it is NOT in any
cache data structures. While the use of this directive might
accidental releases of information via unanticipated accesses to
of certain users and service authors who are concerned about
The purpose of this directive is to meet the stated requirements
possible after forwarding it.
remove the information from volatile storage as promptly as
non-volatile storage, and MUST make a best-effort attempt to
that the cache MUST NOT intentionally store the information in
shared and shared caches. "MUST NOT store" in this context means
request that elicited it. This directive applies to both non-
a cache MUST NOT store any part of either this response or the
either this request or any response to it. If sent in a response,
request. If sent in a request, a cache MUST NOT store any part of
entire message, and MAY be sent either in a response or in a
example, on backup tapes). The no-store directive applies to the
inadvertent release or retention of sensitive information (for
The purpose of the no-store directive is to prevent the
Indicates that the response MUST NOT be stored under any circumstances.
def no_store? self['no-store'] end
def parse(value)
def parse(value) return if value.nil? || value.empty? value.delete(' ').split(',').each do |part| next if part.empty? name, value = part.split('=', 2) self[name.downcase] = (value || true) unless name.empty? end self end
def private?
response may be cached, and cannot ensure the privacy of the
Note: This usage of the word private only controls where the
MAY cache the response.
response for requests by other users. A private (non-shared) cache
response are intended for only one user and are not a valid
allows an origin server to state that the specified parts of the
a single user and MUST NOT be cached by a shared cache. This
Indicates that all or part of the response message is intended for
def private? self['private'] end
def proxy_revalidate?
Note that such authenticated responses also need the public cache
(in order to make sure that each user has been authenticated).
requiring proxies that service many users to revalidate each time
it has already been authenticated once by that user), while still
later return the response without needing to revalidate it (since
authenticated request to permit the user's cache to store and
user agent caches. It can be used on a response to an
revalidate directive, except that it does not apply to non-shared
The proxy-revalidate directive has the same meaning as the must-
def proxy_revalidate? self['proxy-revalidate'] end
def public?
private directive is not set and the request does not include an
A response may be considered public without this directive if the
shared cache.
would normally be non-cacheable or cacheable only within a non-
Indicates that the response MAY be cached by any cache, even if it
def public? self['public'] end
def reverse_max_age
with the origin server. The r-maxage directive is always ignored by
stale to respond to a subsequent request without first revalidating it
i.e., that the reverse cache must not use the entry after it becomes
directive also implies the semantics of the proxy-revalidate directive.
directive, the s-maxage directive, or the expires header. The r-maxage
this directive overrides the maximum age specified by either the max-age
(but not for a private or proxy cache), the maximum age specified by
If a response includes a r-maxage directive, then for a reverse cache
def reverse_max_age self['r-maxage'].to_i if key?('r-maxage') end
def shared_max_age
the origin server. The s-maxage directive is always ignored by a
to respond to a subsequent request without first revalidating it with
that the shared cache must not use the entry after it becomes stale
also implies the semantics of the proxy-revalidate directive. i.e.,
max-age directive or the expires header. The s-maxage directive
this directive overrides the maximum age specified by either the
cache (but not for a private cache), the maximum age specified by
If a response includes an s-maxage directive, then for a shared
def shared_max_age self['s-maxage'].to_i if key?('s-maxage') end
def to_s
def to_s bools, vals = [], [] each do |key,value| if value == true bools << key elsif value vals << "#{key}=#{value}" end end (bools.sort + vals.sort).join(', ') end