public static CacheValidationStatus ValidateCacheOn5XXResponse(HttpRequestCacheValidator ctx) {
/*
If a cache receives a 5xx response while attempting to revalidate an
entry, it MAY either forward this response to the requesting client,
or act as if the server failed to respond. In the latter case, it MAY
return a previously received response unless the cached entry
includes the "must-revalidate" cache-control directive
*/
// Do we have cached item?
if (ctx.CacheStream == Stream.Null || ctx.CacheStatusCode == (HttpStatusCode)0) {
return CacheValidationStatus.DoNotTakeFromCache;
}
if (ctx.CacheEntityLength != ctx.CacheEntry.StreamSize || ctx.CacheStatusCode == HttpStatusCode.PartialContent) {
// Partial cache remains partial, user will not know that.
// This is because user either did not provide a Range Header or
// the user range was just forwarded to the server bypassing cache
return CacheValidationStatus.DoNotTakeFromCache;
}
if (ValidateCacheBySpecialCases(ctx) != TriState.Valid) {
// This response cannot be used without _successful_ revalidation
return CacheValidationStatus.DoNotTakeFromCache;
}
if (ctx.Policy.Level == HttpRequestCacheLevel.CacheOnly || ctx.Policy.Level == HttpRequestCacheLevel.CacheIfAvailable || ctx.Policy.Level == HttpRequestCacheLevel.CacheOrNextCacheOnly)
{
// that was a cache only request
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_sxx_resp_cache_only));
return CacheValidationStatus.ReturnCachedResponse;
}
if (ctx.Policy.Level == HttpRequestCacheLevel.Default || ctx.Policy.Level == HttpRequestCacheLevel.Revalidate)
{
if (ValidateCacheByClientPolicy(ctx)) {
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_sxx_resp_can_be_replaced));
ctx.CacheHeaders.Add(HttpKnownHeaderNames.Warning, HttpRequestCacheValidator.Warning_111);
return CacheValidationStatus.ReturnCachedResponse;
}
}
return CacheValidationStatus.DoNotTakeFromCache;
}