public static CacheValidationStatus OnValidateResponse(HttpRequestCacheValidator ctx)
{
//
// At this point we assume that policy >= CacheOrNextCacheOnly && policy < Refresh
//
// If there was a retry already, it should go with cache disabled so by default we won't retry it again
if (ctx.ResponseCount > 1) {
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_accept_based_on_retry_count, ctx.ResponseCount));
return CacheValidationStatus.Continue;
}
// We don't convert user-range request to a conditional one
if (ctx.RequestRangeUser) {
// was a user range request, we did not touch it.
return CacheValidationStatus.Continue;
}
//If a live response has older Date, then request should be retried
if (ctx.CacheDate != DateTime.MinValue &&
ctx.ResponseDate != DateTime.MinValue &&
ctx.CacheDate > ctx.ResponseDate) {
if(Logging.On)Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_date_header_older_than_cache_entry));
Common.ConstructUnconditionalRefreshRequest(ctx);
return CacheValidationStatus.RetryResponseFromServer;
}
HttpWebResponse resp = ctx.Response as HttpWebResponse;
if (ctx.RequestRangeCache && resp.StatusCode == HttpStatusCode.RequestedRangeNotSatisfiable) {
if(Logging.On)Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_server_didnt_satisfy_range, ctx.Request.Headers[HttpKnownHeaderNames.Range]));
Common.ConstructUnconditionalRefreshRequest(ctx);
return CacheValidationStatus.RetryResponseFromServer;
}
if (resp.StatusCode == HttpStatusCode.NotModified)
{
if (ctx.RequestIfHeader1 == null)
{
if(Logging.On)Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_304_received_on_unconditional_request));
Common.ConstructUnconditionalRefreshRequest(ctx);
return CacheValidationStatus.RetryResponseFromServer;
}
else if (ctx.RequestRangeCache)
{
// The way _we_ create range requests shoyuld never result in 304
if(Logging.On)Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_304_received_on_unconditional_request_expected_200_206));
Common.ConstructUnconditionalRefreshRequest(ctx);
return CacheValidationStatus.RetryResponseFromServer;
}
}
if (ctx.CacheHttpVersion.Major <= 1 && resp.ProtocolVersion.Major <=1 &&
ctx.CacheHttpVersion.Minor < 1 && resp.ProtocolVersion.Minor <1 &&
ctx.CacheLastModified > ctx.ResponseLastModified)
{
if(Logging.On)Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_last_modified_header_older_than_cache_entry));
// On http <= 1.0 cache LastModified > resp LastModified
Common.ConstructUnconditionalRefreshRequest(ctx);
return CacheValidationStatus.RetryResponseFromServer;
}
if (ctx.Policy.Level == HttpRequestCacheLevel.Default && ctx.ResponseAge != TimeSpan.MinValue) {
// If the client has requested MaxAge/MinFresh/MaxStale
// check does the response meet the requirements
if ( (ctx.ResponseAge > ctx.Policy.MaxAge) ||
(ctx.ResponseExpires != DateTime.MinValue &&
(ctx.Policy.MinFresh > TimeSpan.Zero && (ctx.ResponseExpires - DateTime.UtcNow) < ctx.Policy.MinFresh) ||
(ctx.Policy.MaxStale > TimeSpan.Zero && (DateTime.UtcNow - ctx.ResponseExpires) > ctx.Policy.MaxStale)))
{
if(Logging.On)Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_freshness_outside_policy_limits));
Common.ConstructUnconditionalRefreshRequest(ctx);
return CacheValidationStatus.RetryResponseFromServer;
}
}
//Cleanup what we've done to this request since protcol can resubmit for auth or redirect.
if (ctx.RequestIfHeader1 != null) {
ctx.Request.Headers.RemoveInternal(ctx.RequestIfHeader1);
ctx.RequestIfHeader1 = null;
}
if (ctx.RequestIfHeader2 != null) {
ctx.Request.Headers.RemoveInternal(ctx.RequestIfHeader2);
ctx.RequestIfHeader2 = null;
}
if (ctx.RequestRangeCache) {
ctx.Request.Headers.RemoveInternal(HttpKnownHeaderNames.Range);
ctx.RequestRangeCache = false;
}
return CacheValidationStatus.Continue;
}