private CacheValidationStatus UpdateCache() { CacheValidationStatus status = this._Validator.UpdateCache(); this._Validator.SetValidationStatus(status); return(status); }
protected RequestCacheValidator(bool strictCacheErrors, TimeSpan unspecifiedMaxAge) { this._StrictCacheErrors = strictCacheErrors; this._UnspecifiedMaxAge = unspecifiedMaxAge; this._ValidationStatus = CacheValidationStatus.DoNotUseCache; this._CacheFreshnessStatus = System.Net.Cache.CacheFreshnessStatus.Undefined; }
/* * // * protected RequestCacheValidator(): this(false, TimeSpan.FromDays(1)) * { * } */ protected RequestCacheValidator(bool strictCacheErrors, TimeSpan unspecifiedMaxAge) { _StrictCacheErrors = strictCacheErrors; _UnspecifiedMaxAge = unspecifiedMaxAge; _ValidationStatus = CacheValidationStatus.DoNotUseCache; _CacheFreshnessStatus = CacheFreshnessStatus.Undefined; }
/// <summary> /// Needs to run before action runs /// </summary> /// <param name="context"></param> /// <returns>Whether continue or not. If false then the action MUST not run</returns> public async Task <bool> Before(HttpContext context) { _cacheCowHeader = new CacheCowHeader(); _cacheValidated = null; _isRequestCacheable = _validator.IsCacheable(context.Request); _cacheValidationStatus = context.Request.GetCacheValidationStatus(); if (_cacheValidationStatus != CacheValidationStatus.None) { var timedETag = await _cacheDirectiveProvider.QueryAsync(context); _cacheCowHeader.QueryMadeAndSuccessful = timedETag != null; _cacheValidated = ApplyCacheValidation(timedETag, _cacheValidationStatus, context); _cacheCowHeader.ValidationApplied = true; if (_cacheValidated ?? false) { _cacheCowHeader.ShortCircuited = true; _cacheCowHeader.ValidationMatched = HttpMethods.IsGet(context.Request.Method); // NOTE: In GET match result in short-circuit and in PUT the opposite context.Response.Headers.Add(CacheCowHeader.Name, _cacheCowHeader.ToString()); // the response would have been set and no need to run the rest of the pipeline return(false); } } _stream = context.Response.Body; context.Response.Body = new MemoryStream(); return(true); }
// private CacheValidationStatus UpdateCache() { CacheValidationStatus result = _Validator.UpdateCache(); _Validator.SetValidationStatus(result); return(result); }
internal CacheValidationStatus GetUpdateStatus(WebResponse response, Stream responseStream) { if (response == null) { throw new ArgumentNullException("response"); } if (this._ProtocolStatus == CacheValidationStatus.DoNotUseCache) { return(CacheValidationStatus.DoNotUseCache); } try { if (Logging.On) { Logging.Enter(Logging.RequestCache, this, "GetUpdateStatus", (string)null); } if (this._Validator.Response == null) { this._Validator.FetchResponse(response); } if (this._ProtocolStatus == CacheValidationStatus.RemoveFromCache) { this.EnsureCacheRemoval(this._Validator.CacheKey); return(this._ProtocolStatus); } if (((this._ProtocolStatus != CacheValidationStatus.DoNotTakeFromCache) && (this._ProtocolStatus != CacheValidationStatus.ReturnCachedResponse)) && (this._ProtocolStatus != CacheValidationStatus.CombineCachedAndServerResponse)) { if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_not_updated_based_on_cache_protocol_status", new object[] { "GetUpdateStatus()", this._ProtocolStatus.ToString() })); } return(this._ProtocolStatus); } this.CheckUpdateOnResponse(responseStream); } catch (Exception exception) { this._ProtocolException = exception; this._ProtocolStatus = CacheValidationStatus.Fail; if (((exception is ThreadAbortException) || (exception is StackOverflowException)) || (exception is OutOfMemoryException)) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_object_and_exception", new object[] { "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (exception is WebException) ? exception.Message : exception.ToString() })); } } finally { if (Logging.On) { Logging.Exit(Logging.RequestCache, this, "GetUpdateStatus", "result = " + this._ProtocolStatus.ToString()); } } return(this._ProtocolStatus); }
private CacheValidationStatus ValidateResponse() { CacheValidationStatus status = this._Validator.ValidateResponse(); this._Validator.SetValidationStatus(status); if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_result", new object[] { "ValidateResponse()", status.ToString() })); } return(status); }
// private CacheValidationStatus ValidateResponse() { CacheValidationStatus result = _Validator.ValidateResponse(); _Validator.SetValidationStatus(result); if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_result, "ValidateResponse()", result.ToString())); } return(result); }
private CacheValidationStatus ValidateRequest() { if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, string.Concat(new object[] { "Request#", this._Validator.Request.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), ", Policy = ", this._Validator.Request.CachePolicy.ToString(), ", Cache Uri = ", this._Validator.Uri })); } CacheValidationStatus status = this._Validator.ValidateRequest(); this._Validator.SetValidationStatus(status); if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, "Selected cache Key = " + this._Validator.CacheKey); } return(status); }
internal void FetchRequest(System.Uri uri, WebRequest request) { this._Request = request; this._Policy = request.CachePolicy; this._Response = null; this._ResponseCount = 0; this._ValidationStatus = CacheValidationStatus.DoNotUseCache; this._CacheFreshnessStatus = System.Net.Cache.CacheFreshnessStatus.Undefined; this._CacheStream = null; this._CacheStreamOffset = 0L; this._CacheStreamLength = 0L; if (!uri.Equals(this._Uri)) { this._CacheKey = uri.GetParts(UriComponents.AbsoluteUri, UriFormat.Unescaped); } this._Uri = uri; }
// // This optional method is only for protocols supporting a revalidation concept // For a retried request this method must be called again. // internal CacheValidationStatus GetRevalidateStatus(WebResponse response, Stream responseStream) { if (response == null) { throw new ArgumentNullException("response"); } if (_ProtocolStatus == CacheValidationStatus.DoNotUseCache) { return(CacheValidationStatus.DoNotUseCache); } // If we returned cached response, switch the state to not call cache anymore. if (_ProtocolStatus == CacheValidationStatus.ReturnCachedResponse) { _ProtocolStatus = CacheValidationStatus.DoNotUseCache; return(_ProtocolStatus); } try { if (Logging.On) { Logging.Enter(Logging.RequestCache, this, "GetRevalidateStatus", (_Validator == null? null: _Validator.Request)); } _Validator.FetchResponse(response); if (_ProtocolStatus != CacheValidationStatus.Continue && _ProtocolStatus != CacheValidationStatus.RetryResponseFromServer) { if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_revalidation_not_needed, "GetRevalidateStatus()")); } return(_ProtocolStatus); } CheckRetrieveOnResponse(responseStream); } finally { if (Logging.On) { Logging.Exit(Logging.RequestCache, this, "GetRevalidateStatus", "result = " + _ProtocolStatus.ToString()); } } return(_ProtocolStatus); }
/*-------------- internal members -------------*/ // internal void FetchRequest(Uri uri, WebRequest request) { _Request = request; _Policy = request.CachePolicy; _Response = null; _ResponseCount = 0; _ValidationStatus = CacheValidationStatus.DoNotUseCache; _CacheFreshnessStatus = CacheFreshnessStatus.Undefined; _CacheStream = null; _CacheStreamOffset = 0L; _CacheStreamLength = 0L; if (!uri.Equals(_Uri)) { // it's changed from previous call _CacheKey = uri.GetParts(UriComponents.AbsoluteUri, UriFormat.Unescaped); } _Uri = uri; }
// private CacheValidationStatus ValidateRequest() { if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, "Request#" + _Validator.Request.GetHashCode().ToString(NumberFormatInfo.InvariantInfo) + ", Policy = " + _Validator.Request.CachePolicy.ToString() + ", Cache Uri = " + _Validator.Uri); } CacheValidationStatus result = _Validator.ValidateRequest(); _Validator.SetValidationStatus(result); if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, "Selected cache Key = " + _Validator.CacheKey); } return(result); }
internal CacheValidationStatus GetRevalidateStatus(WebResponse response, Stream responseStream) { if (response == null) { throw new ArgumentNullException("response"); } if (this._ProtocolStatus == CacheValidationStatus.DoNotUseCache) { return(CacheValidationStatus.DoNotUseCache); } if (this._ProtocolStatus == CacheValidationStatus.ReturnCachedResponse) { this._ProtocolStatus = CacheValidationStatus.DoNotUseCache; return(this._ProtocolStatus); } try { if (Logging.On) { Logging.Enter(Logging.RequestCache, this, "GetRevalidateStatus", (this._Validator == null) ? null : this._Validator.Request); } this._Validator.FetchResponse(response); if ((this._ProtocolStatus != CacheValidationStatus.Continue) && (this._ProtocolStatus != CacheValidationStatus.RetryResponseFromServer)) { if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_revalidation_not_needed", new object[] { "GetRevalidateStatus()" })); } return(this._ProtocolStatus); } this.CheckRetrieveOnResponse(responseStream); } finally { if (Logging.On) { Logging.Exit(Logging.RequestCache, this, "GetRevalidateStatus", "result = " + this._ProtocolStatus.ToString()); } } return(this._ProtocolStatus); }
internal void SetValidationStatus(CacheValidationStatus status) { _ValidationStatus = status; }
// // This is (optionally) called after receiveing a live response // protected internal override CacheValidationStatus RevalidateCache() { if (HttpProxyMode) { return(base.RevalidateCache()); } if (Policy.Level >= RequestCacheLevel.Reload) { // For those policies cache is never returned GlobalLog.Assert("RevalidateCache()", "This validator should not be called for policy = " + Policy.ToString()); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_validator_invalid_for_policy, Policy.ToString())); } return(CacheValidationStatus.DoNotTakeFromCache); } // First check is do we still hold on a cached entry? if (CacheStream == Stream.Null) { return(CacheValidationStatus.DoNotTakeFromCache); } // // This is a second+ time validation after receiving at least one response // CacheValidationStatus result = CacheValidationStatus.DoNotTakeFromCache; FtpWebResponse resp = Response as FtpWebResponse; if (resp == null) { // This will result to an application error return(CacheValidationStatus.DoNotTakeFromCache); } if (resp.StatusCode == FtpStatusCode.FileStatus) { if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_response_last_modified, resp.LastModified.ToUniversalTime().ToString("r", CultureInfo.InvariantCulture), resp.ContentLength)); } if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_cache_last_modified, CacheEntry.LastModifiedUtc.ToString("r", CultureInfo.InvariantCulture), CacheEntry.StreamSize)); } if (CacheStreamOffset != 0L && CacheEntry.IsPartialEntry) { //should never happen if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_partial_and_non_zero_content_offset, CacheStreamOffset.ToString(CultureInfo.InvariantCulture))); } result = CacheValidationStatus.DoNotTakeFromCache; } if (resp.LastModified.ToUniversalTime() == CacheEntry.LastModifiedUtc) { if (CacheEntry.IsPartialEntry) { // A caller will need to use Validator.CacheEntry.StreamSize to figure out what the restart point is if (resp.ContentLength > 0) { this.CacheStreamLength = resp.ContentLength; } else { this.CacheStreamLength = -1; } result = CacheValidationStatus.CombineCachedAndServerResponse; } else if (resp.ContentLength == CacheEntry.StreamSize) { result = CacheValidationStatus.ReturnCachedResponse; } else { result = CacheValidationStatus.DoNotTakeFromCache; } } else { result = CacheValidationStatus.DoNotTakeFromCache; } } else { result = CacheValidationStatus.DoNotTakeFromCache; } return(result); }
/* // protected RequestCacheValidator(): this(false, TimeSpan.FromDays(1)) { } */ protected RequestCacheValidator(bool strictCacheErrors, TimeSpan unspecifiedMaxAge) { _StrictCacheErrors = strictCacheErrors; _UnspecifiedMaxAge = unspecifiedMaxAge; _ValidationStatus = CacheValidationStatus.DoNotUseCache; _CacheFreshnessStatus = CacheFreshnessStatus.Undefined; }
private void CheckRetrieveBeforeSubmit() { try { RequestCacheEntry entry; Label_0000: if ((this._Validator.CacheStream != null) && (this._Validator.CacheStream != Stream.Null)) { this._Validator.CacheStream.Close(); this._Validator.CacheStream = Stream.Null; } if (this._Validator.StrictCacheErrors) { this._Validator.CacheStream = this._RequestCache.Retrieve(this._Validator.CacheKey, out entry); } else { Stream stream; this._RequestCache.TryRetrieve(this._Validator.CacheKey, out entry, out stream); this._Validator.CacheStream = stream; } if (entry == null) { entry = new RequestCacheEntry { IsPrivateEntry = this._RequestCache.IsPrivateCache }; this._Validator.FetchCacheEntry(entry); } if (this._Validator.CacheStream == null) { this._Validator.CacheStream = Stream.Null; } this.ValidateFreshness(entry); this._ProtocolStatus = this.ValidateCache(); switch (this._ProtocolStatus) { case CacheValidationStatus.DoNotUseCache: case CacheValidationStatus.DoNotTakeFromCache: return; case CacheValidationStatus.Fail: this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_fail", new object[] { "ValidateCache" })); return; case CacheValidationStatus.RetryResponseFromCache: goto Label_0000; case CacheValidationStatus.ReturnCachedResponse: if ((this._Validator.CacheStream != null) && (this._Validator.CacheStream != Stream.Null)) { break; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_no_cache_entry", new object[] { "ValidateCache()" })); } this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_no_stream", new object[] { this._Validator.CacheKey })); return; case CacheValidationStatus.Continue: this._ResponseStream = this._Validator.CacheStream; return; default: goto Label_02CB; } Stream cacheStream = this._Validator.CacheStream; this._RequestCache.UnlockEntry(this._Validator.CacheStream); if ((this._Validator.CacheStreamOffset != 0L) || (this._Validator.CacheStreamLength != this._Validator.CacheEntry.StreamSize)) { cacheStream = new RangeStream(cacheStream, this._Validator.CacheStreamOffset, this._Validator.CacheStreamLength); if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_returned_range_cache", new object[] { "ValidateCache()", this._Validator.CacheStreamOffset, this._Validator.CacheStreamLength })); } } this._ResponseStream = cacheStream; this._ResponseStreamLength = this._Validator.CacheStreamLength; return; Label_02CB: this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_result", new object[] { "ValidateCache", this._Validator.ValidationStatus.ToString() })); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_unexpected_status", new object[] { "ValidateCache()", this._Validator.ValidationStatus.ToString() })); } } catch (Exception exception) { this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = exception; if (((exception is ThreadAbortException) || (exception is StackOverflowException)) || (exception is OutOfMemoryException)) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_object_and_exception", new object[] { "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (exception is WebException) ? exception.Message : exception.ToString() })); } } finally { if (((this._ResponseStream == null) && (this._Validator.CacheStream != null)) && (this._Validator.CacheStream != Stream.Null)) { this._Validator.CacheStream.Close(); this._Validator.CacheStream = Stream.Null; } } }
/// <summary> /// Happens at the incoming (executING) /// </summary> /// <param name="timedEtag"></param> /// <param name="cacheValidationStatus"></param> /// <param name="context"> /// </param> /// <returns> /// True: applied and the call can exit /// False: tried to apply but did not match hence the call should continue /// null: could not apply (timedEtag was null) /// </returns> protected bool?ApplyCacheValidation(TimedEntityTagHeaderValue timedEtag, CacheValidationStatus cacheValidationStatus, ContextUnifier context) { if (timedEtag == null) { return(null); } switch (cacheValidationStatus) { case CacheValidationStatus.GetIfModifiedSince: if (timedEtag.LastModified == null) { return(false); } else { if (timedEtag.LastModified > context.Request.Headers.IfModifiedSince.Value) { return(false); } else { context.Response = new HttpResponseMessage(HttpStatusCode.NotModified); return(true); } } case CacheValidationStatus.GetIfNoneMatch: if (timedEtag.ETag == null) { return(false); } else { if (context.Request.Headers.IfNoneMatch.Any(x => x.Tag == timedEtag.ETag.Tag)) { context.Response = new HttpResponseMessage(HttpStatusCode.NotModified); return(true); } else { return(false); } } case CacheValidationStatus.PutPatchDeleteIfMatch: if (timedEtag.ETag == null) { return(false); } else { if (context.Request.Headers.IfMatch.Any(x => x.Tag == timedEtag.ETag.Tag)) { return(false); } else { context.Response = new HttpResponseMessage(HttpStatusCode.PreconditionFailed); return(true); } } case CacheValidationStatus.PutPatchDeleteIfUnModifiedSince: if (timedEtag.LastModified == null) { return(false); } else { if (timedEtag.LastModified > context.Request.Headers.IfUnmodifiedSince.Value) { context.Response = new HttpResponseMessage(HttpStatusCode.PreconditionFailed); return(true); } else { return(false); } } default: return(null); } }
internal CacheValidationStatus GetRetrieveStatus(Uri cacheUri, WebRequest request) { if (cacheUri == null) { throw new ArgumentNullException("cacheUri"); } if (request == null) { throw new ArgumentNullException("request"); } if (!this._CanTakeNewRequest || (this._ProtocolStatus == CacheValidationStatus.RetryResponseFromServer)) { return(CacheValidationStatus.Continue); } this._CanTakeNewRequest = false; this._ResponseStream = null; this._ResponseStreamLength = 0L; this._ProtocolStatus = CacheValidationStatus.Continue; this._ProtocolException = null; if (Logging.On) { Logging.Enter(Logging.RequestCache, this, "GetRetrieveStatus", request); } try { if ((request.CachePolicy == null) || (request.CachePolicy.Level == RequestCacheLevel.BypassCache)) { this._ProtocolStatus = CacheValidationStatus.DoNotUseCache; return(this._ProtocolStatus); } if ((this._RequestCache == null) || (this._Validator == null)) { this._ProtocolStatus = CacheValidationStatus.DoNotUseCache; return(this._ProtocolStatus); } this._Validator.FetchRequest(cacheUri, request); switch ((this._ProtocolStatus = this.ValidateRequest())) { case CacheValidationStatus.DoNotUseCache: case CacheValidationStatus.DoNotTakeFromCache: case CacheValidationStatus.Continue: break; case CacheValidationStatus.Fail: this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_fail", new object[] { "ValidateRequest" })); break; default: this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_result", new object[] { "ValidateRequest", this._Validator.ValidationStatus.ToString() })); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_unexpected_status", new object[] { "ValidateRequest()", this._Validator.ValidationStatus.ToString() })); } break; } if (this._ProtocolStatus != CacheValidationStatus.Continue) { return(this._ProtocolStatus); } this.CheckRetrieveBeforeSubmit(); } catch (Exception exception) { this._ProtocolException = exception; this._ProtocolStatus = CacheValidationStatus.Fail; if (((exception is ThreadAbortException) || (exception is StackOverflowException)) || (exception is OutOfMemoryException)) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_object_and_exception", new object[] { "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (exception is WebException) ? exception.Message : exception.ToString() })); } } finally { if (Logging.On) { Logging.Exit(Logging.RequestCache, this, "GetRetrieveStatus", "result = " + this._ProtocolStatus.ToString()); } } return(this._ProtocolStatus); }
private void CheckUpdateOnResponse(Stream responseStream) { if (this._Validator.CacheEntry == null) { RequestCacheEntry fetchEntry = new RequestCacheEntry { IsPrivateEntry = this._RequestCache.IsPrivateCache }; this._Validator.FetchCacheEntry(fetchEntry); } string cacheKey = this._Validator.CacheKey; bool flag = true; try { Stream stream; switch ((this._ProtocolStatus = this.UpdateCache())) { case CacheValidationStatus.DoNotUseCache: case CacheValidationStatus.DoNotUpdateCache: return; case CacheValidationStatus.Fail: this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_fail", new object[] { "UpdateCache" })); return; case CacheValidationStatus.CacheResponse: if (!this._Validator.StrictCacheErrors) { break; } stream = this._RequestCache.Store(this._Validator.CacheKey, this._Validator.CacheEntry.StreamSize, this._Validator.CacheEntry.ExpiresUtc, this._Validator.CacheEntry.LastModifiedUtc, this._Validator.CacheEntry.MaxStale, this._Validator.CacheEntry.EntryMetadata, this._Validator.CacheEntry.SystemMetadata); goto Label_022C; case CacheValidationStatus.UpdateResponseInformation: this._ResponseStream = new MetadataUpdateStream(responseStream, this._RequestCache, this._Validator.CacheKey, this._Validator.CacheEntry.ExpiresUtc, this._Validator.CacheEntry.LastModifiedUtc, this._Validator.CacheEntry.LastSynchronizedUtc, this._Validator.CacheEntry.MaxStale, this._Validator.CacheEntry.EntryMetadata, this._Validator.CacheEntry.SystemMetadata, this._Validator.StrictCacheErrors); flag = false; this._ProtocolStatus = CacheValidationStatus.UpdateResponseInformation; return; case CacheValidationStatus.RemoveFromCache: this.EnsureCacheRemoval(cacheKey); flag = false; return; default: goto Label_0298; } this._RequestCache.TryStore(this._Validator.CacheKey, this._Validator.CacheEntry.StreamSize, this._Validator.CacheEntry.ExpiresUtc, this._Validator.CacheEntry.LastModifiedUtc, this._Validator.CacheEntry.MaxStale, this._Validator.CacheEntry.EntryMetadata, this._Validator.CacheEntry.SystemMetadata, out stream); Label_022C: if (stream == null) { this._ProtocolStatus = CacheValidationStatus.DoNotUpdateCache; } else { this._ResponseStream = new ForwardingReadStream(responseStream, stream, this._Validator.CacheStreamOffset, this._Validator.StrictCacheErrors); this._ProtocolStatus = CacheValidationStatus.UpdateResponseInformation; } return; Label_0298: this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_result", new object[] { "UpdateCache", this._Validator.ValidationStatus.ToString() })); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_unexpected_status", new object[] { "UpdateCache()", this._Validator.ValidationStatus.ToString() })); } } finally { if (flag) { this._RequestCache.UnlockEntry(this._Validator.CacheStream); } } }
// // This will decide on cache update and construct the effective response stream // private void CheckUpdateOnResponse(Stream responseStream) { if (_Validator.CacheEntry == null) { // There was no chance to create an empty entry yet RequestCacheEntry cacheEntry = new RequestCacheEntry(); cacheEntry.IsPrivateEntry = _RequestCache.IsPrivateCache; _Validator.FetchCacheEntry(cacheEntry); } // With NoCache we may end up storing whole response as a new entry in Cache. // Otherwise we may end up updating Context+Metadata or just Context // // In any case we may end up doing nothing. // string retrieveKey = _Validator.CacheKey; bool unlockEntry = true; try { switch (_ProtocolStatus=UpdateCache()) { case CacheValidationStatus.RemoveFromCache: EnsureCacheRemoval(retrieveKey); unlockEntry = false; break; case CacheValidationStatus.UpdateResponseInformation: // NB: Just invoked validator must have updated CacheEntry and transferred // ONLY allowed headers from the response to the Context.xxxMetadata member _ResponseStream = new MetadataUpdateStream( responseStream, _RequestCache, _Validator.CacheKey, _Validator.CacheEntry.ExpiresUtc, _Validator.CacheEntry.LastModifiedUtc, _Validator.CacheEntry.LastSynchronizedUtc, _Validator.CacheEntry.MaxStale, _Validator.CacheEntry.EntryMetadata, _Validator.CacheEntry.SystemMetadata, _Validator.StrictCacheErrors); // // This can be looked as a design hole since we have to keep the entry // locked for the case when we want to update that previously retrieved entry. // I think RequestCache contract should allow to detect that a new physical cache entry // does not match to the "entry being updated" and so to should ignore updates on replaced entries. // unlockEntry = false; _ProtocolStatus = CacheValidationStatus.UpdateResponseInformation; break; case CacheValidationStatus.CacheResponse: // NB: Just invoked validator must have updated CacheEntry and transferred // ONLY allowed headers from the response to the Context.xxxMetadata member Stream stream; if (_Validator.StrictCacheErrors) {stream = _RequestCache.Store(_Validator.CacheKey, _Validator.CacheEntry.StreamSize, _Validator.CacheEntry.ExpiresUtc, _Validator.CacheEntry.LastModifiedUtc, _Validator.CacheEntry.MaxStale, _Validator.CacheEntry.EntryMetadata, _Validator.CacheEntry.SystemMetadata);} else {_RequestCache.TryStore(_Validator.CacheKey, _Validator.CacheEntry.StreamSize, _Validator.CacheEntry.ExpiresUtc, _Validator.CacheEntry.LastModifiedUtc, _Validator.CacheEntry.MaxStale, _Validator.CacheEntry.EntryMetadata, _Validator.CacheEntry.SystemMetadata, out stream);} // Wrap the response stream into forwarding one if (stream == null) { _ProtocolStatus = CacheValidationStatus.DoNotUpdateCache; } else { _ResponseStream = new ForwardingReadStream(responseStream, stream, _Validator.CacheStreamOffset, _Validator.StrictCacheErrors); _ProtocolStatus = CacheValidationStatus.UpdateResponseInformation; } break; case CacheValidationStatus.DoNotUseCache: case CacheValidationStatus.DoNotUpdateCache: break; case CacheValidationStatus.Fail: _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "UpdateCache")); break; default: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "UpdateCache", _Validator.ValidationStatus.ToString())); if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "UpdateCache()", _Validator.ValidationStatus.ToString())); break; } } finally { if (unlockEntry) { // The entry can now be replaced as we are not going for cache entry metadata-only update _RequestCache.UnlockEntry(_Validator.CacheStream); } } }
// private void CheckRetrieveOnResponse(Stream responseStream) { GlobalLog.Assert(_ProtocolStatus == CacheValidationStatus.Continue || _ProtocolStatus == CacheValidationStatus.RetryResponseFromServer, "CheckRetrieveOnResponse()|Unexpected _ProtocolStatus = ", _ProtocolStatus); bool closeCacheStream = true; try { // This will inspect the live response on the correctness matter switch (_ProtocolStatus = ValidateResponse()) { case CacheValidationStatus.Continue: closeCacheStream = false; // The response looks good break; case CacheValidationStatus.RetryResponseFromServer: closeCacheStream = false; break; case CacheValidationStatus.Fail: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "ValidateResponse")); break; case CacheValidationStatus.DoNotUseCache: break; default: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "ValidateResponse", _Validator.ValidationStatus.ToString())); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "ValidateResponse()", _Validator.ValidationStatus.ToString())); } break; } } catch (Exception e) { closeCacheStream = true; _ProtocolException = e; _ProtocolStatus = CacheValidationStatus.Fail; if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString()))); } } finally { // This is to release cache entry in case we are not interested in it if (closeCacheStream && _ResponseStream != null) { _ResponseStream.Close(); _ResponseStream = null; _Validator.CacheStream = Stream.Null; } } if (_ProtocolStatus != CacheValidationStatus.Continue) { return; } // // only CacheValidationStatus.Continue goes here with closeCacheStream == false // try { // switch (_ProtocolStatus = RevalidateCache()) { case CacheValidationStatus.DoNotUseCache: case CacheValidationStatus.RemoveFromCache: case CacheValidationStatus.DoNotTakeFromCache: closeCacheStream = true; break; case CacheValidationStatus.ReturnCachedResponse: if (_Validator.CacheStream == null || _Validator.CacheStream == Stream.Null) { _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_no_stream, _Validator.CacheKey)); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_null_cached_stream, "RevalidateCache()")); } break; } Stream stream = _Validator.CacheStream; if (_Validator.CacheStreamOffset != 0L || _Validator.CacheStreamLength != _Validator.CacheEntry.StreamSize) { stream = new RangeStream(stream, _Validator.CacheStreamOffset, _Validator.CacheStreamLength); if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_returned_range_cache, "RevalidateCache()", _Validator.CacheStreamOffset, _Validator.CacheStreamLength)); } } _ResponseStream = stream; _ResponseStreamLength = _Validator.CacheStreamLength; break; case CacheValidationStatus.CombineCachedAndServerResponse: if (_Validator.CacheStream == null || _Validator.CacheStream == Stream.Null) { _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_no_stream, _Validator.CacheKey)); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_requested_combined_but_null_cached_stream, "RevalidateCache()")); } break; } if (responseStream != null) { stream = new CombinedReadStream(_Validator.CacheStream, responseStream); } else { // So Abort can close the cache stream stream = _Validator.CacheStream; } _ResponseStream = stream; _ResponseStreamLength = _Validator.CacheStreamLength; break; case CacheValidationStatus.Fail: closeCacheStream = true; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "RevalidateCache")); break; default: closeCacheStream = true; _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "RevalidateCache", _Validator.ValidationStatus.ToString())); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "RevalidateCache()", _Validator.ValidationStatus.ToString())); } break; } } catch (Exception e) { closeCacheStream = true; _ProtocolException = e; _ProtocolStatus = CacheValidationStatus.Fail; if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString()))); } } finally { // This is to release cache entry in case we are not interested in it if (closeCacheStream && _ResponseStream != null) { _ResponseStream.Close(); _ResponseStream = null; _Validator.CacheStream = Stream.Null; } } }
// // Private methods // // // This method may be invoked as part of the request submission but before issuing a live request // private void CheckRetrieveBeforeSubmit() { GlobalLog.Assert(_ProtocolStatus == CacheValidationStatus.Continue, "CheckRetrieveBeforeSubmit()|Unexpected _ProtocolStatus = {0}", _ProtocolStatus); try { while (true) { RequestCacheEntry cacheEntry; if (_Validator.CacheStream != null && _Validator.CacheStream != Stream.Null) { // Reset to Initial state _Validator.CacheStream.Close(); _Validator.CacheStream = Stream.Null; } if (_Validator.StrictCacheErrors) { _Validator.CacheStream = _RequestCache.Retrieve(_Validator.CacheKey, out cacheEntry); } else { Stream stream; _RequestCache.TryRetrieve(_Validator.CacheKey, out cacheEntry, out stream); _Validator.CacheStream = stream; } if (cacheEntry == null) { cacheEntry = new RequestCacheEntry(); cacheEntry.IsPrivateEntry = _RequestCache.IsPrivateCache; _Validator.FetchCacheEntry(cacheEntry); } if (_Validator.CacheStream == null) { // If entry does not have a stream an empty stream wrapper must be returned. // A null or Stream.Null value stands for non existent cache entry. _Validator.CacheStream = Stream.Null; } ValidateFreshness(cacheEntry); _ProtocolStatus = ValidateCache(); // This will tell us what to do next switch (_ProtocolStatus) { case CacheValidationStatus.ReturnCachedResponse: if (_Validator.CacheStream == null || _Validator.CacheStream == Stream.Null) { if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_no_cache_entry, "ValidateCache()")); _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_no_stream, _Validator.CacheKey)); break; } // Final decision is made, check on a range response from cache Stream stream = _Validator.CacheStream; // The entry can now be replaced as we are not going for cache entry metadata-only update _RequestCache.UnlockEntry(_Validator.CacheStream); if (_Validator.CacheStreamOffset != 0L || _Validator.CacheStreamLength != _Validator.CacheEntry.StreamSize) { stream = new RangeStream(stream, _Validator.CacheStreamOffset, _Validator.CacheStreamLength); if(Logging.On) Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_returned_range_cache, "ValidateCache()", _Validator.CacheStreamOffset, _Validator.CacheStreamLength)); } _ResponseStream = stream; _ResponseStreamLength = _Validator.CacheStreamLength; break; case CacheValidationStatus.Continue: // copy a cache stream ref _ResponseStream = _Validator.CacheStream; break; case CacheValidationStatus.RetryResponseFromCache: // loop thought cache retrieve continue; case CacheValidationStatus.DoNotTakeFromCache: case CacheValidationStatus.DoNotUseCache: break; case CacheValidationStatus.Fail: _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "ValidateCache")); break; default: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "ValidateCache", _Validator.ValidationStatus.ToString())); if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "ValidateCache()", _Validator.ValidationStatus.ToString())); break; } break; } } catch (Exception e) { _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = e; if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString()))); } finally { // This is to release cache entry on error if (_ResponseStream == null && _Validator.CacheStream != null && _Validator.CacheStream != Stream.Null) { _Validator.CacheStream.Close(); _Validator.CacheStream = Stream.Null; } } }
// // This optional method is only for protocols supporting a revalidation concept // For a retried request this method must be called again. // internal CacheValidationStatus GetRevalidateStatus (WebResponse response, Stream responseStream) { if (response == null) throw new ArgumentNullException("response"); if (_ProtocolStatus == CacheValidationStatus.DoNotUseCache) return CacheValidationStatus.DoNotUseCache; // If we returned cached response, switch the state to not call cache anymore. if (_ProtocolStatus == CacheValidationStatus.ReturnCachedResponse) { _ProtocolStatus = CacheValidationStatus.DoNotUseCache; return _ProtocolStatus; } try { if(Logging.On) Logging.Enter(Logging.RequestCache, this, "GetRevalidateStatus", (_Validator == null? null: _Validator.Request)); _Validator.FetchResponse(response); if (_ProtocolStatus != CacheValidationStatus.Continue && _ProtocolStatus != CacheValidationStatus.RetryResponseFromServer) { if(Logging.On) Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_revalidation_not_needed, "GetRevalidateStatus()")); return _ProtocolStatus; } CheckRetrieveOnResponse(responseStream); } finally { if(Logging.On) Logging.Exit(Logging.RequestCache, this, "GetRevalidateStatus", "result = " + _ProtocolStatus.ToString()); } return _ProtocolStatus; }
private void CheckRetrieveOnResponse(Stream responseStream) { bool flag = true; try { switch ((this._ProtocolStatus = this.ValidateResponse())) { case CacheValidationStatus.DoNotUseCache: goto Label_01CA; case CacheValidationStatus.Fail: this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_fail", new object[] { "ValidateResponse" })); goto Label_01CA; case CacheValidationStatus.RetryResponseFromServer: flag = false; goto Label_01CA; case CacheValidationStatus.Continue: flag = false; goto Label_01CA; } this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_result", new object[] { "ValidateResponse", this._Validator.ValidationStatus.ToString() })); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_unexpected_status", new object[] { "ValidateResponse()", this._Validator.ValidationStatus.ToString() })); } } catch (Exception exception) { flag = true; this._ProtocolException = exception; this._ProtocolStatus = CacheValidationStatus.Fail; if (((exception is ThreadAbortException) || (exception is StackOverflowException)) || (exception is OutOfMemoryException)) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_object_and_exception", new object[] { "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (exception is WebException) ? exception.Message : exception.ToString() })); } } finally { if (flag && (this._ResponseStream != null)) { this._ResponseStream.Close(); this._ResponseStream = null; this._Validator.CacheStream = Stream.Null; } } Label_01CA: if (this._ProtocolStatus != CacheValidationStatus.Continue) { return; } try { switch ((this._ProtocolStatus = this.RevalidateCache())) { case CacheValidationStatus.DoNotUseCache: case CacheValidationStatus.DoNotTakeFromCache: case CacheValidationStatus.RemoveFromCache: flag = true; return; case CacheValidationStatus.Fail: flag = true; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_fail", new object[] { "RevalidateCache" })); return; case CacheValidationStatus.ReturnCachedResponse: if ((this._Validator.CacheStream != null) && (this._Validator.CacheStream != Stream.Null)) { break; } this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_no_stream", new object[] { this._Validator.CacheKey })); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_null_cached_stream", new object[] { "RevalidateCache()" })); } return; case CacheValidationStatus.CombineCachedAndServerResponse: if ((this._Validator.CacheStream != null) && (this._Validator.CacheStream != Stream.Null)) { goto Label_03FF; } this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_no_stream", new object[] { this._Validator.CacheKey })); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_requested_combined_but_null_cached_stream", new object[] { "RevalidateCache()" })); } return; default: goto Label_046E; } Stream cacheStream = this._Validator.CacheStream; if ((this._Validator.CacheStreamOffset != 0L) || (this._Validator.CacheStreamLength != this._Validator.CacheEntry.StreamSize)) { cacheStream = new RangeStream(cacheStream, this._Validator.CacheStreamOffset, this._Validator.CacheStreamLength); if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_returned_range_cache", new object[] { "RevalidateCache()", this._Validator.CacheStreamOffset, this._Validator.CacheStreamLength })); } } this._ResponseStream = cacheStream; this._ResponseStreamLength = this._Validator.CacheStreamLength; return; Label_03FF: if (responseStream != null) { cacheStream = new CombinedReadStream(this._Validator.CacheStream, responseStream); } else { cacheStream = this._Validator.CacheStream; } this._ResponseStream = cacheStream; this._ResponseStreamLength = this._Validator.CacheStreamLength; return; Label_046E: flag = true; this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_result", new object[] { "RevalidateCache", this._Validator.ValidationStatus.ToString() })); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_unexpected_status", new object[] { "RevalidateCache()", this._Validator.ValidationStatus.ToString() })); } } catch (Exception exception2) { flag = true; this._ProtocolException = exception2; this._ProtocolStatus = CacheValidationStatus.Fail; if (((exception2 is ThreadAbortException) || (exception2 is StackOverflowException)) || (exception2 is OutOfMemoryException)) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_object_and_exception", new object[] { "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (exception2 is WebException) ? exception2.Message : exception2.ToString() })); } } finally { if (flag && (this._ResponseStream != null)) { this._ResponseStream.Close(); this._ResponseStream = null; this._Validator.CacheStream = Stream.Null; } } }
/// <summary> /// Happens at the incoming (executING) /// </summary> /// <param name="timedEtag"></param> /// <param name="cacheValidationStatus"></param> /// <param name="context"> /// </param> /// <returns> /// True: applied and the call can exit /// False: tried to apply but did not match hence the call should continue /// null: could not apply (timedEtag was null) /// </returns> protected bool?ApplyCacheValidation(TimedEntityTagHeaderValue timedEtag, CacheValidationStatus cacheValidationStatus, ResourceExecutingContext context) { if (timedEtag == null) { return(null); } var headers = context.HttpContext.Request.GetTypedHeadersWithCaching(); switch (cacheValidationStatus) { case CacheValidationStatus.GetIfModifiedSince: if (timedEtag.LastModified == null) { return(false); } else { if (timedEtag.LastModified > headers.IfModifiedSince.Value) { return(false); } else { context.Result = new StatusCodeResult(StatusCodes.Status304NotModified); context.HttpContext.Response.StatusCode = StatusCodes.Status304NotModified; return(true); } } case CacheValidationStatus.GetIfNoneMatch: if (timedEtag.ETag == null) { return(false); } else { if (headers.IfNoneMatch.Any(x => x.Tag == timedEtag.ETag.Tag)) { context.Result = new StatusCodeResult(StatusCodes.Status304NotModified); context.HttpContext.Response.StatusCode = StatusCodes.Status304NotModified; return(true); } else { return(false); } } case CacheValidationStatus.PutIfMatch: if (timedEtag.ETag == null) { return(false); } else { if (headers.IfMatch.Any(x => x.Tag == timedEtag.ETag.Tag)) { return(false); } else { context.Result = new StatusCodeResult(StatusCodes.Status409Conflict); context.HttpContext.Response.StatusCode = StatusCodes.Status409Conflict; return(true); } } case CacheValidationStatus.PutIfUnModifiedSince: if (timedEtag.LastModified == null) { return(false); } else { if (timedEtag.LastModified > headers.IfUnmodifiedSince.Value) { context.Result = new StatusCodeResult(StatusCodes.Status409Conflict); context.HttpContext.Response.StatusCode = StatusCodes.Status409Conflict; return(true); } else { return(false); } } default: return(null); } }
internal CacheValidationStatus GetUpdateStatus(WebResponse response, Stream responseStream) { if (response == null) { throw new ArgumentNullException("response"); } if (this._ProtocolStatus == CacheValidationStatus.DoNotUseCache) { return CacheValidationStatus.DoNotUseCache; } try { if (Logging.On) { Logging.Enter(Logging.RequestCache, this, "GetUpdateStatus", (string) null); } if (this._Validator.Response == null) { this._Validator.FetchResponse(response); } if (this._ProtocolStatus == CacheValidationStatus.RemoveFromCache) { this.EnsureCacheRemoval(this._Validator.CacheKey); return this._ProtocolStatus; } if (((this._ProtocolStatus != CacheValidationStatus.DoNotTakeFromCache) && (this._ProtocolStatus != CacheValidationStatus.ReturnCachedResponse)) && (this._ProtocolStatus != CacheValidationStatus.CombineCachedAndServerResponse)) { if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_not_updated_based_on_cache_protocol_status", new object[] { "GetUpdateStatus()", this._ProtocolStatus.ToString() })); } return this._ProtocolStatus; } this.CheckUpdateOnResponse(responseStream); } catch (Exception exception) { this._ProtocolException = exception; this._ProtocolStatus = CacheValidationStatus.Fail; if (((exception is ThreadAbortException) || (exception is StackOverflowException)) || (exception is OutOfMemoryException)) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_object_and_exception", new object[] { "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (exception is WebException) ? exception.Message : exception.ToString() })); } } finally { if (Logging.On) { Logging.Exit(Logging.RequestCache, this, "GetUpdateStatus", "result = " + this._ProtocolStatus.ToString()); } } return this._ProtocolStatus; }
// // Private methods // // // This method may be invoked as part of the request submission but before issuing a live request // private void CheckRetrieveBeforeSubmit() { GlobalLog.Assert(_ProtocolStatus == CacheValidationStatus.Continue, "CheckRetrieveBeforeSubmit()|Unexpected _ProtocolStatus = {0}", _ProtocolStatus); try { while (true) { RequestCacheEntry cacheEntry; if (_Validator.CacheStream != null && _Validator.CacheStream != Stream.Null) { // Reset to Initial state _Validator.CacheStream.Close(); _Validator.CacheStream = Stream.Null; } if (_Validator.StrictCacheErrors) { _Validator.CacheStream = _RequestCache.Retrieve(_Validator.CacheKey, out cacheEntry); } else { Stream stream; _RequestCache.TryRetrieve(_Validator.CacheKey, out cacheEntry, out stream); _Validator.CacheStream = stream; } if (cacheEntry == null) { cacheEntry = new RequestCacheEntry(); cacheEntry.IsPrivateEntry = _RequestCache.IsPrivateCache; _Validator.FetchCacheEntry(cacheEntry); } if (_Validator.CacheStream == null) { // If entry does not have a stream an empty stream wrapper must be returned. // A null or Stream.Null value stands for non existent cache entry. _Validator.CacheStream = Stream.Null; } ValidateFreshness(cacheEntry); _ProtocolStatus = ValidateCache(); // This will tell us what to do next switch (_ProtocolStatus) { case CacheValidationStatus.ReturnCachedResponse: if (_Validator.CacheStream == null || _Validator.CacheStream == Stream.Null) { if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_no_cache_entry, "ValidateCache()")); } _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_no_stream, _Validator.CacheKey)); break; } // Final decision is made, check on a range response from cache Stream stream = _Validator.CacheStream; // The entry can now be replaced as we are not going for cache entry metadata-only update _RequestCache.UnlockEntry(_Validator.CacheStream); if (_Validator.CacheStreamOffset != 0L || _Validator.CacheStreamLength != _Validator.CacheEntry.StreamSize) { stream = new RangeStream(stream, _Validator.CacheStreamOffset, _Validator.CacheStreamLength); if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_returned_range_cache, "ValidateCache()", _Validator.CacheStreamOffset, _Validator.CacheStreamLength)); } } _ResponseStream = stream; _ResponseStreamLength = _Validator.CacheStreamLength; break; case CacheValidationStatus.Continue: // copy a cache stream ref _ResponseStream = _Validator.CacheStream; break; case CacheValidationStatus.RetryResponseFromCache: // loop thought cache retrieve continue; case CacheValidationStatus.DoNotTakeFromCache: case CacheValidationStatus.DoNotUseCache: break; case CacheValidationStatus.Fail: _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "ValidateCache")); break; default: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "ValidateCache", _Validator.ValidationStatus.ToString())); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "ValidateCache()", _Validator.ValidationStatus.ToString())); } break; } break; } } catch (Exception e) { _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = e; if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString()))); } } finally { // This is to release cache entry on error if (_ResponseStream == null && _Validator.CacheStream != null && _Validator.CacheStream != Stream.Null) { _Validator.CacheStream.Close(); _Validator.CacheStream = Stream.Null; } } }
// // This will decide on cache update and construct the effective response stream // private void CheckUpdateOnResponse(Stream responseStream) { if (_Validator.CacheEntry == null) { // There was no chance to create an empty entry yet RequestCacheEntry cacheEntry = new RequestCacheEntry(); cacheEntry.IsPrivateEntry = _RequestCache.IsPrivateCache; _Validator.FetchCacheEntry(cacheEntry); } // With NoCache we may end up storing whole response as a new entry in Cache. // Otherwise we may end up updating Context+Metadata or just Context // // In any case we may end up doing nothing. // string retrieveKey = _Validator.CacheKey; bool unlockEntry = true; try { switch (_ProtocolStatus = UpdateCache()) { case CacheValidationStatus.RemoveFromCache: EnsureCacheRemoval(retrieveKey); unlockEntry = false; break; case CacheValidationStatus.UpdateResponseInformation: // NB: Just invoked validator must have updated CacheEntry and transferred // ONLY allowed headers from the response to the Context.xxxMetadata member _ResponseStream = new MetadataUpdateStream( responseStream, _RequestCache, _Validator.CacheKey, _Validator.CacheEntry.ExpiresUtc, _Validator.CacheEntry.LastModifiedUtc, _Validator.CacheEntry.LastSynchronizedUtc, _Validator.CacheEntry.MaxStale, _Validator.CacheEntry.EntryMetadata, _Validator.CacheEntry.SystemMetadata, _Validator.StrictCacheErrors); // // This can be looked as a design hole since we have to keep the entry // locked for the case when we want to update that previously retrieved entry. // I think RequestCache contract should allow to detect that a new physical cache entry // does not match to the "entry being updated" and so to should ignore updates on replaced entries. // unlockEntry = false; _ProtocolStatus = CacheValidationStatus.UpdateResponseInformation; break; case CacheValidationStatus.CacheResponse: // NB: Just invoked validator must have updated CacheEntry and transferred // ONLY allowed headers from the response to the Context.xxxMetadata member Stream stream; if (_Validator.StrictCacheErrors) { stream = _RequestCache.Store(_Validator.CacheKey, _Validator.CacheEntry.StreamSize, _Validator.CacheEntry.ExpiresUtc, _Validator.CacheEntry.LastModifiedUtc, _Validator.CacheEntry.MaxStale, _Validator.CacheEntry.EntryMetadata, _Validator.CacheEntry.SystemMetadata); } else { _RequestCache.TryStore(_Validator.CacheKey, _Validator.CacheEntry.StreamSize, _Validator.CacheEntry.ExpiresUtc, _Validator.CacheEntry.LastModifiedUtc, _Validator.CacheEntry.MaxStale, _Validator.CacheEntry.EntryMetadata, _Validator.CacheEntry.SystemMetadata, out stream); } // Wrap the response stream into forwarding one _ResponseStream = new ForwardingReadStream(responseStream, stream, _Validator.CacheStreamOffset, _Validator.StrictCacheErrors); _ProtocolStatus = CacheValidationStatus.UpdateResponseInformation; break; case CacheValidationStatus.DoNotUseCache: case CacheValidationStatus.DoNotUpdateCache: break; case CacheValidationStatus.Fail: _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "UpdateCache")); break; default: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "UpdateCache", _Validator.ValidationStatus.ToString())); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "UpdateCache()", _Validator.ValidationStatus.ToString())); } break; } } finally { if (unlockEntry) { // The entry can now be replaced as we are not going for cache entry metadata-only update _RequestCache.UnlockEntry(_Validator.CacheStream); } } }
/// <summary> /// Happens at the incoming (executING) /// </summary> /// <param name="timedEtag"></param> /// <param name="cacheValidationStatus"></param> /// <param name="context"> /// </param> /// <returns> /// True: applied and the call can exit (short-circuit) /// False: tried to apply but did not match hence the call should continue /// null: could not apply (timedEtag was null) /// </returns> protected bool?ApplyCacheValidation(TimedEntityTagHeaderValue timedEtag, CacheValidationStatus cacheValidationStatus, HttpContext context) { if (timedEtag == null) { return(null); } var headers = context.Request.GetTypedHeadersWithCaching(); switch (cacheValidationStatus) { case CacheValidationStatus.GetIfModifiedSince: if (timedEtag.LastModified == null) { return(false); } else { if (timedEtag.LastModified > headers.IfModifiedSince.Value) { return(false); } else { context.Response.StatusCode = StatusCodes.Status304NotModified; return(true); } } case CacheValidationStatus.GetIfNoneMatch: if (timedEtag.ETag == null) { return(false); } else { if (headers.IfNoneMatch.Any(x => x.Tag == timedEtag.ETag.Tag)) { context.Response.StatusCode = StatusCodes.Status304NotModified; return(true); } else { return(false); } } case CacheValidationStatus.PutPatchDeleteIfMatch: if (timedEtag.ETag == null) { return(false); } else { if (headers.IfMatch.Any(x => x.Tag == timedEtag.ETag.Tag)) { return(false); } else { context.Response.StatusCode = StatusCodes.Status412PreconditionFailed; return(true); } } case CacheValidationStatus.PutPatchDeleteIfUnModifiedSince: if (timedEtag.LastModified == null) { return(false); } else { if (timedEtag.LastModified > headers.IfUnmodifiedSince.Value) { context.Response.StatusCode = StatusCodes.Status412PreconditionFailed; return(true); } else { return(false); } } default: return(null); } }
internal CacheValidationStatus GetRevalidateStatus(WebResponse response, Stream responseStream) { if (response == null) { throw new ArgumentNullException("response"); } if (this._ProtocolStatus == CacheValidationStatus.DoNotUseCache) { return CacheValidationStatus.DoNotUseCache; } if (this._ProtocolStatus == CacheValidationStatus.ReturnCachedResponse) { this._ProtocolStatus = CacheValidationStatus.DoNotUseCache; return this._ProtocolStatus; } try { if (Logging.On) { Logging.Enter(Logging.RequestCache, this, "GetRevalidateStatus", (this._Validator == null) ? null : this._Validator.Request); } this._Validator.FetchResponse(response); if ((this._ProtocolStatus != CacheValidationStatus.Continue) && (this._ProtocolStatus != CacheValidationStatus.RetryResponseFromServer)) { if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_revalidation_not_needed", new object[] { "GetRevalidateStatus()" })); } return this._ProtocolStatus; } this.CheckRetrieveOnResponse(responseStream); } finally { if (Logging.On) { Logging.Exit(Logging.RequestCache, this, "GetRevalidateStatus", "result = " + this._ProtocolStatus.ToString()); } } return this._ProtocolStatus; }
// internal CacheValidationStatus GetRetrieveStatus(Uri cacheUri, WebRequest request) { if (cacheUri == null) { throw new ArgumentNullException("cacheUri"); } if (request == null) { throw new ArgumentNullException("request"); } if (!_CanTakeNewRequest || _ProtocolStatus == CacheValidationStatus.RetryResponseFromServer) { return(CacheValidationStatus.Continue); } _CanTakeNewRequest = false; // Reset protocol state _ResponseStream = null; _ResponseStreamLength = 0L; _ProtocolStatus = CacheValidationStatus.Continue; _ProtocolException = null; if (Logging.On) { Logging.Enter(Logging.RequestCache, this, "GetRetrieveStatus", request); } try { if (request.CachePolicy == null || request.CachePolicy.Level == RequestCacheLevel.BypassCache) { _ProtocolStatus = CacheValidationStatus.DoNotUseCache; return(_ProtocolStatus); } if (_RequestCache == null || _Validator == null) { _ProtocolStatus = CacheValidationStatus.DoNotUseCache; return(_ProtocolStatus); } _Validator.FetchRequest(cacheUri, request); switch (_ProtocolStatus = ValidateRequest()) { case CacheValidationStatus.Continue: // This is a green light for cache protocol break; case CacheValidationStatus.DoNotTakeFromCache: // no cache but response can be cached case CacheValidationStatus.DoNotUseCache: // ignore cache entirely break; case CacheValidationStatus.Fail: _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "ValidateRequest")); break; default: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "ValidateRequest", _Validator.ValidationStatus.ToString())); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "ValidateRequest()", _Validator.ValidationStatus.ToString())); } break; } if (_ProtocolStatus != CacheValidationStatus.Continue) { return(_ProtocolStatus); } // // Proceed with validation // CheckRetrieveBeforeSubmit(); } catch (Exception e) { _ProtocolException = e; _ProtocolStatus = CacheValidationStatus.Fail; if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString()))); } } finally { if (Logging.On) { Logging.Exit(Logging.RequestCache, this, "GetRetrieveStatus", "result = " + _ProtocolStatus.ToString()); } } return(_ProtocolStatus); }
protected internal override CacheValidationStatus RevalidateCache() { if (this.HttpProxyMode) { return(base.RevalidateCache()); } if (this.Policy.Level >= RequestCacheLevel.Reload) { if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_validator_invalid_for_policy", new object[] { this.Policy.ToString() })); } return(CacheValidationStatus.DoNotTakeFromCache); } if (base.CacheStream != Stream.Null) { CacheValidationStatus doNotTakeFromCache = CacheValidationStatus.DoNotTakeFromCache; FtpWebResponse response = base.Response as FtpWebResponse; if (response == null) { return(CacheValidationStatus.DoNotTakeFromCache); } if (response.StatusCode != FtpStatusCode.FileStatus) { return(CacheValidationStatus.DoNotTakeFromCache); } if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_response_last_modified", new object[] { response.LastModified.ToUniversalTime().ToString("r", CultureInfo.InvariantCulture), response.ContentLength })); } if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_cache_last_modified", new object[] { base.CacheEntry.LastModifiedUtc.ToString("r", CultureInfo.InvariantCulture), base.CacheEntry.StreamSize })); } if ((base.CacheStreamOffset != 0L) && base.CacheEntry.IsPartialEntry) { if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_partial_and_non_zero_content_offset", new object[] { base.CacheStreamOffset.ToString(CultureInfo.InvariantCulture) })); } doNotTakeFromCache = CacheValidationStatus.DoNotTakeFromCache; } if (!(response.LastModified.ToUniversalTime() == base.CacheEntry.LastModifiedUtc)) { return(CacheValidationStatus.DoNotTakeFromCache); } if (base.CacheEntry.IsPartialEntry) { if (response.ContentLength > 0L) { base.CacheStreamLength = response.ContentLength; } else { base.CacheStreamLength = -1L; } return(CacheValidationStatus.CombineCachedAndServerResponse); } if (response.ContentLength == base.CacheEntry.StreamSize) { return(CacheValidationStatus.ReturnCachedResponse); } } return(CacheValidationStatus.DoNotTakeFromCache); }
// // Returns UpdateResponseInformation if passed response stream has to be replaced (cache is updated in some way) // Returns Fail if request is to fail // Any other return value should be ignored // internal CacheValidationStatus GetUpdateStatus (WebResponse response, Stream responseStream) { if (response == null) throw new ArgumentNullException("response"); if (_ProtocolStatus == CacheValidationStatus.DoNotUseCache) return CacheValidationStatus.DoNotUseCache; try { if(Logging.On) Logging.Enter(Logging.RequestCache, this, "GetUpdateStatus", null); if (_Validator.Response == null) _Validator.FetchResponse(response); if (_ProtocolStatus == CacheValidationStatus.RemoveFromCache) { EnsureCacheRemoval(_Validator.CacheKey); return _ProtocolStatus; } if (_ProtocolStatus != CacheValidationStatus.DoNotTakeFromCache && _ProtocolStatus != CacheValidationStatus.ReturnCachedResponse && _ProtocolStatus != CacheValidationStatus.CombineCachedAndServerResponse) { if(Logging.On) Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_not_updated_based_on_cache_protocol_status, "GetUpdateStatus()", _ProtocolStatus.ToString())); return _ProtocolStatus; } CheckUpdateOnResponse(responseStream); } catch (Exception e) { _ProtocolException = e; _ProtocolStatus = CacheValidationStatus.Fail; if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString()))); } finally { if(Logging.On)Logging.Exit(Logging.RequestCache, this, "GetUpdateStatus", "result = " + _ProtocolStatus.ToString()); } return _ProtocolStatus; }
// private void CheckRetrieveOnResponse(Stream responseStream) { GlobalLog.Assert(_ProtocolStatus == CacheValidationStatus.Continue || _ProtocolStatus == CacheValidationStatus.RetryResponseFromServer, "CheckRetrieveOnResponse()|Unexpected _ProtocolStatus = ", _ProtocolStatus); // if something goes wrong we release cache stream if any exists bool closeCacheStream = true; try { // This will inspect the live response on the correctness matter switch (_ProtocolStatus = ValidateResponse()) { case CacheValidationStatus.Continue: closeCacheStream = false; // The response looks good break; case CacheValidationStatus.RetryResponseFromServer: // The response is broken will need to retry or give up closeCacheStream = false; break; case CacheValidationStatus.Fail: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "ValidateResponse")); break; case CacheValidationStatus.DoNotUseCache: break; default: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "ValidateResponse", _Validator.ValidationStatus.ToString())); if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "ValidateResponse()", _Validator.ValidationStatus.ToString())); break; } } catch (Exception e) { closeCacheStream = true; _ProtocolException = e; _ProtocolStatus = CacheValidationStatus.Fail; if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString()))); } finally { // This is to release cache entry in case we are not interested in it if (closeCacheStream && _ResponseStream != null) { _ResponseStream.Close(); _ResponseStream = null; _Validator.CacheStream = Stream.Null; } } if (_ProtocolStatus != CacheValidationStatus.Continue) { return; } // // only CacheValidationStatus.Continue goes here with closeCacheStream == false // try { // This will tell us what to do next // Note this is a second time question to the caching protocol about a cached entry // Except that we now have live response to consider // // The validator can at any time replace the cache stream and update cache Metadata (aka headers). // switch (_ProtocolStatus = RevalidateCache()) { case CacheValidationStatus.DoNotUseCache: case CacheValidationStatus.RemoveFromCache: case CacheValidationStatus.DoNotTakeFromCache: closeCacheStream = true; break; case CacheValidationStatus.ReturnCachedResponse: if (_Validator.CacheStream == null || _Validator.CacheStream == Stream.Null) { _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_no_stream, _Validator.CacheKey)); if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_null_cached_stream, "RevalidateCache()")); break; } Stream stream = _Validator.CacheStream; if (_Validator.CacheStreamOffset != 0L || _Validator.CacheStreamLength != _Validator.CacheEntry.StreamSize) { stream = new RangeStream(stream, _Validator.CacheStreamOffset, _Validator.CacheStreamLength); if(Logging.On) Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_returned_range_cache, "RevalidateCache()", _Validator.CacheStreamOffset, _Validator.CacheStreamLength)); } _ResponseStream = stream; _ResponseStreamLength = _Validator.CacheStreamLength; break; case CacheValidationStatus.CombineCachedAndServerResponse: if (_Validator.CacheStream == null || _Validator.CacheStream == Stream.Null) { _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_no_stream, _Validator.CacheKey)); if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_requested_combined_but_null_cached_stream, "RevalidateCache()")); break; } // // FTP cannot give the tail of the combined stream at that point // Consider: Revisit the design of the CacheProtocol class if (responseStream != null) { stream = new CombinedReadStream(_Validator.CacheStream, responseStream); } else { // So Abort can close the cache stream stream = _Validator.CacheStream; } _ResponseStream = stream; _ResponseStreamLength = _Validator.CacheStreamLength; break; case CacheValidationStatus.Fail: closeCacheStream = true; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "RevalidateCache")); break; default: closeCacheStream = true; _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "RevalidateCache", _Validator.ValidationStatus.ToString())); if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "RevalidateCache()", _Validator.ValidationStatus.ToString())); break; } } catch (Exception e) { closeCacheStream = true; _ProtocolException = e; _ProtocolStatus = CacheValidationStatus.Fail; if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString()))); } finally { // This is to release cache entry in case we are not interested in it if (closeCacheStream && _ResponseStream != null) { _ResponseStream.Close(); _ResponseStream = null; _Validator.CacheStream = Stream.Null; } } }
// internal CacheValidationStatus GetRetrieveStatus (Uri cacheUri, WebRequest request) { if (cacheUri == null) throw new ArgumentNullException("cacheUri"); if (request == null) throw new ArgumentNullException("request"); if (!_CanTakeNewRequest || _ProtocolStatus == CacheValidationStatus.RetryResponseFromServer) return CacheValidationStatus.Continue; _CanTakeNewRequest = false; // Reset protocol state _ResponseStream = null; _ResponseStreamLength = 0L; _ProtocolStatus = CacheValidationStatus.Continue; _ProtocolException = null; if(Logging.On) Logging.Enter(Logging.RequestCache, this, "GetRetrieveStatus", request); try { if (request.CachePolicy == null || request.CachePolicy.Level == RequestCacheLevel.BypassCache) { _ProtocolStatus = CacheValidationStatus.DoNotUseCache; return _ProtocolStatus; } if (_RequestCache == null || _Validator == null) { _ProtocolStatus = CacheValidationStatus.DoNotUseCache; return _ProtocolStatus; } _Validator.FetchRequest(cacheUri, request); switch(_ProtocolStatus = ValidateRequest()) { case CacheValidationStatus.Continue: // This is a green light for cache protocol break; case CacheValidationStatus.DoNotTakeFromCache: // no cache but response can be cached case CacheValidationStatus.DoNotUseCache: // ignore cache entirely break; case CacheValidationStatus.Fail: _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "ValidateRequest")); break; default: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "ValidateRequest", _Validator.ValidationStatus.ToString())); if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "ValidateRequest()", _Validator.ValidationStatus.ToString())); break; } if (_ProtocolStatus != CacheValidationStatus.Continue) return _ProtocolStatus; // // Proceed with validation // CheckRetrieveBeforeSubmit(); } catch (Exception e) { _ProtocolException = e; _ProtocolStatus = CacheValidationStatus.Fail; if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) throw; if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString()))); } finally { if(Logging.On) Logging.Exit(Logging.RequestCache, this, "GetRetrieveStatus", "result = " + _ProtocolStatus.ToString()); } return _ProtocolStatus; }
internal CacheValidationStatus GetRetrieveStatus(Uri cacheUri, WebRequest request) { if (cacheUri == null) { throw new ArgumentNullException("cacheUri"); } if (request == null) { throw new ArgumentNullException("request"); } if (!this._CanTakeNewRequest || (this._ProtocolStatus == CacheValidationStatus.RetryResponseFromServer)) { return CacheValidationStatus.Continue; } this._CanTakeNewRequest = false; this._ResponseStream = null; this._ResponseStreamLength = 0L; this._ProtocolStatus = CacheValidationStatus.Continue; this._ProtocolException = null; if (Logging.On) { Logging.Enter(Logging.RequestCache, this, "GetRetrieveStatus", request); } try { if ((request.CachePolicy == null) || (request.CachePolicy.Level == RequestCacheLevel.BypassCache)) { this._ProtocolStatus = CacheValidationStatus.DoNotUseCache; return this._ProtocolStatus; } if ((this._RequestCache == null) || (this._Validator == null)) { this._ProtocolStatus = CacheValidationStatus.DoNotUseCache; return this._ProtocolStatus; } this._Validator.FetchRequest(cacheUri, request); switch ((this._ProtocolStatus = this.ValidateRequest())) { case CacheValidationStatus.DoNotUseCache: case CacheValidationStatus.DoNotTakeFromCache: case CacheValidationStatus.Continue: break; case CacheValidationStatus.Fail: this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_fail", new object[] { "ValidateRequest" })); break; default: this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_result", new object[] { "ValidateRequest", this._Validator.ValidationStatus.ToString() })); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_unexpected_status", new object[] { "ValidateRequest()", this._Validator.ValidationStatus.ToString() })); } break; } if (this._ProtocolStatus != CacheValidationStatus.Continue) { return this._ProtocolStatus; } this.CheckRetrieveBeforeSubmit(); } catch (Exception exception) { this._ProtocolException = exception; this._ProtocolStatus = CacheValidationStatus.Fail; if (((exception is ThreadAbortException) || (exception is StackOverflowException)) || (exception is OutOfMemoryException)) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_object_and_exception", new object[] { "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (exception is WebException) ? exception.Message : exception.ToString() })); } } finally { if (Logging.On) { Logging.Exit(Logging.RequestCache, this, "GetRetrieveStatus", "result = " + this._ProtocolStatus.ToString()); } } return this._ProtocolStatus; }