public static CacheValidationStatus OnUpdateCache(HttpRequestCacheValidator ctx) {
if (ctx.CacheStatusCode == HttpStatusCode.NotModified) {
if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_need_to_remove_invalid_cache_entry_304));
return CacheValidationStatus.RemoveFromCache;
}
HttpWebResponse resp = ctx.Response as HttpWebResponse;
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_resp_status, resp.StatusCode));
/*********
Vs Whidbey#127214
It was decided not to play with ResponseContentLocation in our implementation.
A derived class may still want to play.
// Compute new Cache Update Key if Content-Location is present on the response
if (ctx.ResponseContentLocation != null) {
if (!Uri.TryParse(ctx.ResponseContentLocation, true, true, out cacheUri)) {
if(Logging.On)Logging.PrintError(Logging.RequestCache, "Cannot parse Uri from Response Content-Location: " + ctx.ResponseContentLocation);
return CacheValidationStatus.RemoveFromCache;
}
if (!cacheUri.IsAbsoluteUri) {
try {
ctx.CacheKey = new Uri(ctx.RequestUri, cacheUri);
}
catch {
return CacheValidationStatus.RemoveFromCache;
}
}
}
*********/
if (ctx.ValidationStatus == CacheValidationStatus.RemoveFromCache) {
return CacheValidationStatus.RemoveFromCache;
}
CacheValidationStatus noUpdateResult =
(ctx.RequestMethod >= HttpMethod.Post && ctx.RequestMethod <= HttpMethod.Delete || ctx.RequestMethod == HttpMethod.Other)
?CacheValidationStatus.RemoveFromCache
:CacheValidationStatus.DoNotUpdateCache;
if (Common.OnUpdateCache(ctx, resp) != TriState.Valid) {
return noUpdateResult;
}
CacheValidationStatus result = CacheValidationStatus.CacheResponse;
ctx.CacheEntry.IsPartialEntry = false;
if (resp.StatusCode == HttpStatusCode.NotModified || ctx.RequestMethod == HttpMethod.Head)
{
result = CacheValidationStatus.UpdateResponseInformation;
// This may take a shorter path when updating the entry
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_resp_304_or_request_head));
if (ctx.CacheDontUpdateHeaders) {
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_dont_update_cached_headers));
ctx.CacheHeaders = null;
ctx.CacheEntry.ExpiresUtc = ctx.ResponseExpires;
ctx.CacheEntry.LastModifiedUtc = ctx.ResponseLastModified;
if (ctx.Policy.Level == HttpRequestCacheLevel.Default) {
ctx.CacheEntry.MaxStale = ctx.Policy.MaxStale;
}
else {
ctx.CacheEntry.MaxStale = TimeSpan.MinValue;
}
ctx.CacheEntry.LastSynchronizedUtc = DateTime.UtcNow;
}
else {
if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_update_cached_headers));
}
}
else if (resp.StatusCode == HttpStatusCode.PartialContent)
{
// Check on whether the user requested range can be appended to the cache entry
// We only support combining of non-overlapped increasing bytes ranges
if (ctx.CacheEntry.StreamSize != ctx.ResponseRangeStart && ctx.ResponseRangeStart != 0)
{
if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_partial_resp_not_combined_with_existing_entry, ctx.CacheEntry.StreamSize, ctx.ResponseRangeStart));
return noUpdateResult;
}
// We might be appending a live stream to cache BUT user has asked for a specific range.
// Hence don't reset CacheStreamOffset here so the protocol will create a cache forwarding stream that will hide first bytes from the user
if (!ctx.RequestRangeUser) {
ctx.CacheStreamOffset = 0;
}
// Below code assumes that a combined response has been given to the user,
Common.ReplaceOrUpdateCacheHeaders(ctx, resp);
ctx.CacheHttpVersion = resp.ProtocolVersion;
ctx.CacheEntityLength = ctx.ResponseEntityLength;
ctx.CacheStreamLength = ctx.CacheEntry.StreamSize = ctx.ResponseRangeEnd+1;
if (ctx.CacheEntityLength > 0 && ctx.CacheEntityLength == ctx.CacheEntry.StreamSize)
{
//eventually cache is about to store a complete response
Common.Construct200ok(ctx);
}
else
Common.Construct206PartialContent(ctx, 0);
}
else
{
Common.ReplaceOrUpdateCacheHeaders(ctx, resp);
ctx.CacheHttpVersion = resp.ProtocolVersion;
ctx.CacheStatusCode = resp.StatusCode;
ctx.CacheStatusDescription = resp.StatusDescription;
ctx.CacheEntry.StreamSize = resp.ContentLength;
}
return result;
}