internal static TriState ValidateCacheBySpecialCases(HttpRequestCacheValidator ctx) {
/*
no-cache
If the no-cache directive does not specify a field-name, then a
cache MUST NOT use the response to satisfy a subsequent request
without successful revalidation with the origin server. This
allows an origin server to prevent caching even by caches that
have been configured to return stale responses to client requests.
*/
if (ctx.CacheCacheControl.NoCache) {
if (ctx.CacheCacheControl.NoCacheHeaders == null)
{
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_control_no_cache));
return TriState.Invalid;
}
/*
If the no-cache directive does specify one or more field-names, then a cache MAY
use the response to satisfy a subsequent request, subject to any other restrictions
on caching.
However, the specified field-name(s) MUST NOT be sent in the response to
a subsequent request without successful revalidation with the origin server.
This allows an origin server to prevent the re-use of certain header fields
in a response, while still allowing caching of the rest of the response.
*/
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_control_no_cache_removing_some_headers));
for (int i = 0; i < ctx.CacheCacheControl.NoCacheHeaders.Length; ++i) {
ctx.CacheHeaders.Remove(ctx.CacheCacheControl.NoCacheHeaders[i]);
}
}
/*
must-revalidate
When the must-revalidate
directive is present in a response received by a cache, that cache
MUST NOT use the entry after it becomes stale to respond to a
subsequent request without first revalidating it with the origin
server. (I.e., the cache MUST do an end-to-end revalidation every
time, if, based solely on the origin server's Expires or max-age
value, the cached response is stale.)
proxy-revalidate
The proxy-revalidate directive has the same meaning as the must-
revalidate directive, except that it does not apply to non-shared
user agent caches.
*/
if (ctx.CacheCacheControl.MustRevalidate ||
(!ctx.CacheEntry.IsPrivateEntry && ctx.CacheCacheControl.ProxyRevalidate))
{
if (ctx.CacheFreshnessStatus != CacheFreshnessStatus.Fresh) {
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_control_must_revalidate));
return TriState.Invalid;
}
}
/*
When a shared cache (see section 13.7) receives a request
containing an Authorization field, it MUST NOT return the
corresponding response as a reply to any other request, unless one
of the following specific exceptions holds:
1. If the response includes the "s-maxage" cache-control
directive, the cache MAY use that response in replying to a
subsequent request. But (if the specified maximum age has
passed) a proxy cache MUST first revalidate it with the origin
server, using the request-headers from the new request to allow
the origin server to authenticate the new request. (This is the
defined behavior for s-maxage.) If the response includes "s-
maxage=0", the proxy MUST always revalidate it before re-using
it.
2. If the response includes the "must-revalidate" cache-control
directive, the cache MAY use that response in replying to a
subsequent request. But if the response is stale, all caches
MUST first revalidate it with the origin server, using the
request-headers from the new request to allow the origin server
to authenticate the new request.
3. If the response includes the "public" cache-control directive,
it MAY be returned in reply to any subsequent request.
*/
if (ctx.Request.Headers[HttpKnownHeaderNames.Authorization] != null) {
if (ctx.CacheFreshnessStatus != CacheFreshnessStatus.Fresh) {
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_cached_auth_header));
return TriState.Invalid;
}
if (!ctx.CacheEntry.IsPrivateEntry && ctx.CacheCacheControl.SMaxAge == -1 && !ctx.CacheCacheControl.MustRevalidate && !ctx.CacheCacheControl.Public) {
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_cached_auth_header_no_control_directive));
return TriState.Invalid;
}
}
return TriState.Valid;
}