// // Never throws // private Stream MakeMemoryStream(Stream stream) { // GlobalLog.ThreadContract(ThreadKinds.[....], "HttpWebRequest#" + ValidationHelper.HashString(this) + "::MakeMemoryStream"); if (stream == null || stream is SyncMemoryStream) return stream; SyncMemoryStream memoryStream = new SyncMemoryStream(0); // buffered Stream to save off data try { // // Now drain the Stream // if (stream.CanRead) { byte [] buffer = new byte[1024]; int bytesTransferred = 0; // int maxBytesToBuffer = (HttpWebRequest.DefaultMaximumErrorResponseLength == -1)?buffer.Length:HttpWebRequest.DefaultMaximumErrorResponseLength*1024; while ((bytesTransferred = stream.Read(buffer, 0, Math.Min(buffer.Length, maxBytesToBuffer))) > 0) { memoryStream.Write(buffer, 0, bytesTransferred); if(HttpWebRequest.DefaultMaximumErrorResponseLength != -1) maxBytesToBuffer -= bytesTransferred; } } memoryStream.Position = 0; } catch { } finally { try { ICloseEx icloseEx = stream as ICloseEx; if (icloseEx != null) { icloseEx.CloseEx(CloseExState.Silent); } else { stream.Close(); } } catch { } } return memoryStream; }
/// <remarks> This method may add headers under the "Warning" header name </remarks> protected internal override CacheValidationStatus ValidateCache() { if (this.Policy.Level != HttpRequestCacheLevel.Revalidate && base.Policy.Level >= RequestCacheLevel.Reload) { // For those policies cache is never returned GlobalLog.Assert("OnValidateCache()", "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 have a cached entry at all? // Also we include some very special case where cache got a 304 (NotModified) response somehow if (CacheStream == Stream.Null || (int)CacheStatusCode == 0 || CacheStatusCode == HttpStatusCode.NotModified) { if (this.Policy.Level == HttpRequestCacheLevel.CacheOnly) { // Throw because entry was not found and it's cache-only policy FailRequest(WebExceptionStatus.CacheEntryNotFound); } return CacheValidationStatus.DoNotTakeFromCache; } if (RequestMethod == HttpMethod.Head) { // For a HEAD request we release the cache entry stream asap since we will have to suppress it anyway CacheStream.Close(); CacheStream = new SyncMemoryStream(new byte[] {}); } // Apply our best knowledge of HTTP caching and return the result // that can be hooked up and revised by the upper level CacheValidationStatus result = CacheValidationStatus.DoNotTakeFromCache; // // Before request submission validation // // If we return from cache we should remove existing 1xx warnings RemoveWarnings_1xx(); // default values for a response from cache. CacheStreamOffset = 0; CacheStreamLength = CacheEntry.StreamSize; result = Rfc2616.OnValidateCache(this); if (result != CacheValidationStatus.ReturnCachedResponse && this.Policy.Level == HttpRequestCacheLevel.CacheOnly) { // Throw because entry was not found and it's cache-only policy FailRequest(WebExceptionStatus.CacheEntryNotFound); } if (result == CacheValidationStatus.ReturnCachedResponse) { if (CacheFreshnessStatus == CacheFreshnessStatus.Stale) { CacheHeaders.Add(HttpKnownHeaderNames.Warning, HttpRequestCacheValidator.Warning_110); } if (base.Policy.Level == RequestCacheLevel.CacheOnly) { CacheHeaders.Add(HttpKnownHeaderNames.Warning, HttpRequestCacheValidator.Warning_112); } if (HeuristicExpiration && (int)CacheAge.TotalSeconds >= 24*3600) { CacheHeaders.Add(HttpKnownHeaderNames.Warning, HttpRequestCacheValidator.Warning_113); } } if (result == CacheValidationStatus.DoNotTakeFromCache) { // We signal that current cache entry can be only replaced and not updated CacheStatusCode = (HttpStatusCode) 0; } else if (result == CacheValidationStatus.ReturnCachedResponse) { CacheHeaders[HttpKnownHeaderNames.Age] = ((int)(CacheAge.TotalSeconds)).ToString(NumberFormatInfo.InvariantInfo); } return result; }