// only used by internal cache private static void EntryRemovedCallback(string key, object value, CacheItemRemovedReason reason) { Debug.Trace("OutputCache", "EntryRemovedCallback: reason=" + reason + ", key=" + key); DecrementCount(); PerfCounters.DecrementCounter(AppPerfCounter.OUTPUT_CACHE_ENTRIES); PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_TURNOVER_RATE); CachedRawResponse cachedRawResponse = value as CachedRawResponse; if (cachedRawResponse != null) { String kernelCacheUrl = cachedRawResponse._kernelCacheUrl; // if it is kernel cached, the url will be non-null. // if the entry was re-inserted, don't remove kernel entry since it will be updated if (kernelCacheUrl != null && HttpRuntime.CacheInternal.Get(key) == null) { // invalidate kernel cache entry if (HttpRuntime.UseIntegratedPipeline) { UnsafeIISMethods.MgdFlushKernelCache(kernelCacheUrl); } else { UnsafeNativeMethods.InvalidateKernelCache(kernelCacheUrl); } } } }
private static OutputCacheEntry Convert(CachedRawResponse cachedRawResponse, string depKey, string[] fileDependencies) { List <HeaderElement> headerElements = null; ArrayList headers = cachedRawResponse._rawResponse.Headers; int count = (headers != null) ? headers.Count : 0; for (int i = 0; i < count; i++) { if (headerElements == null) { headerElements = new List <HeaderElement>(count); } HttpResponseHeader h = (HttpResponseHeader)(headers[i]); headerElements.Add(new HeaderElement(h.Name, h.Value)); } List <ResponseElement> responseElements = null; ArrayList buffers = cachedRawResponse._rawResponse.Buffers; count = (buffers != null) ? buffers.Count : 0; for (int i = 0; i < count; i++) { if (responseElements == null) { responseElements = new List <ResponseElement>(count); } IHttpResponseElement elem = buffers[i] as IHttpResponseElement; if (elem is HttpFileResponseElement) { HttpFileResponseElement fileElement = elem as HttpFileResponseElement; responseElements.Add(new FileResponseElement(fileElement.FileName, fileElement.Offset, elem.GetSize())); } else if (elem is HttpSubstBlockResponseElement) { HttpSubstBlockResponseElement substElement = elem as HttpSubstBlockResponseElement; responseElements.Add(new SubstitutionResponseElement(substElement.Callback)); } else { byte[] b = elem.GetBytes(); long length = (b != null) ? b.Length : 0; responseElements.Add(new MemoryResponseElement(b, length)); } } OutputCacheEntry oce = new OutputCacheEntry( cachedRawResponse._cachedVaryId, cachedRawResponse._settings, cachedRawResponse._kernelCacheUrl, depKey, fileDependencies, cachedRawResponse._rawResponse.StatusCode, cachedRawResponse._rawResponse.StatusDescription, headerElements, responseElements ); return(oce); }
static void OnRawResponseRemoved(string key, object value, CacheItemRemovedReason reason) { CachedRawResponse c = (CachedRawResponse)value; c.VaryBy.ItemList.Remove(key); if (c.VaryBy.ItemList.Count != 0) { return; } HttpRuntime.Cache.Remove(c.VaryBy.Key); }
private static OutputCacheEntry Convert(CachedRawResponse cachedRawResponse, string depKey, string[] fileDependencies) { List <HeaderElement> headerElements = null; ArrayList headers = cachedRawResponse._rawResponse.Headers; int capacity = (headers != null) ? headers.Count : 0; for (int i = 0; i < capacity; i++) { if (headerElements == null) { headerElements = new List <HeaderElement>(capacity); } HttpResponseHeader header = (HttpResponseHeader)headers[i]; headerElements.Add(new HeaderElement(header.Name, header.Value)); } List <ResponseElement> responseElements = null; ArrayList buffers = cachedRawResponse._rawResponse.Buffers; capacity = (buffers != null) ? buffers.Count : 0; for (int j = 0; j < capacity; j++) { if (responseElements == null) { responseElements = new List <ResponseElement>(capacity); } IHttpResponseElement element = buffers[j] as IHttpResponseElement; if (element is HttpFileResponseElement) { HttpFileResponseElement element2 = element as HttpFileResponseElement; responseElements.Add(new FileResponseElement(element2.FileName, element2.Offset, element.GetSize())); } else if (element is HttpSubstBlockResponseElement) { HttpSubstBlockResponseElement element3 = element as HttpSubstBlockResponseElement; responseElements.Add(new SubstitutionResponseElement(element3.Callback)); } else { byte[] bytes = element.GetBytes(); long length = (bytes != null) ? ((long)bytes.Length) : ((long)0); responseElements.Add(new MemoryResponseElement(bytes, length)); } } return(new OutputCacheEntry(cachedRawResponse._cachedVaryId, cachedRawResponse._settings, cachedRawResponse._kernelCacheUrl, depKey, fileDependencies, cachedRawResponse._rawResponse.StatusCode, cachedRawResponse._rawResponse.StatusDescription, headerElements, responseElements)); }
void OnRawResponseRemoved(string key, object value, CacheItemRemovedReason reason) { CachedRawResponse c = value as CachedRawResponse; CachedVaryBy varyby = c != null ? c.VaryBy : null; if (varyby == null) { return; } List <string> itemList = varyby.ItemList; OutputCacheProvider provider = FindCacheProvider(null); itemList.Remove(key); provider.Remove(key); if (itemList.Count != 0) { return; } provider.Remove(varyby.Key); }
private static void EntryRemovedCallback(string key, object value, CacheItemRemovedReason reason) { DecrementCount(); PerfCounters.DecrementCounter(AppPerfCounter.OUTPUT_CACHE_ENTRIES); PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_TURNOVER_RATE); CachedRawResponse response = value as CachedRawResponse; if (response != null) { string cacheKey = response._kernelCacheUrl; if ((cacheKey != null) && (HttpRuntime.CacheInternal.Get(key) == null)) { if (HttpRuntime.UseIntegratedPipeline) { UnsafeIISMethods.MgdFlushKernelCache(cacheKey); } else { System.Web.UnsafeNativeMethods.InvalidateKernelCache(cacheKey); } } } }
// insert cached vary or output cache entry internal static void InsertResponse(String cachedVaryKey, CachedVary cachedVary, String rawResponseKey, CachedRawResponse rawResponse, CacheDependency dependencies, DateTime absExp, TimeSpan slidingExp) { // if the provider is undefined or the fragment can't be inserted in the // provider, insert it in the internal cache. OutputCacheProvider provider = GetProvider(HttpContext.Current); // // CachedVary can be serialized. // CachedRawResponse is not always serializable. // bool useProvider = (provider != null); if (useProvider) { bool canUseProvider = (IsSubstBlockSerializable(rawResponse._rawResponse) && rawResponse._settings.IsValidationCallbackSerializable() && slidingExp == Cache.NoSlidingExpiration && (dependencies == null || dependencies.IsFileDependency())); if (useProvider && !canUseProvider) { throw new ProviderException(SR.GetString(SR.Provider_does_not_support_policy_for_responses, provider.Name)); } } #if DBG bool cachedVaryPutInCache = (cachedVary != null); #endif if (cachedVary != null) { /* * Add the CachedVary item so that a request will know * which headers are needed to issue another request. * * Use the Add method so that we guarantee we only use * a single CachedVary and don't overwrite existing ones. */ CachedVary cachedVaryInCache; if (!useProvider) { cachedVaryInCache = OutputCache.UtcAdd(cachedVaryKey, cachedVary); } else { cachedVaryInCache = (CachedVary)provider.Add(cachedVaryKey, cachedVary, Cache.NoAbsoluteExpiration); } if (cachedVaryInCache != null) { if (!cachedVary.Equals(cachedVaryInCache)) { if (!useProvider) { HttpRuntime.CacheInternal.UtcInsert(cachedVaryKey, cachedVary); } else { provider.Set(cachedVaryKey, cachedVary, Cache.NoAbsoluteExpiration); } } else { cachedVary = cachedVaryInCache; #if DBG cachedVaryPutInCache = false; #endif } } if (!useProvider) { AddCacheKeyToDependencies(ref dependencies, cachedVaryKey); } // not all caches support cache key dependencies, but we can use a "change number" to associate // the ControlCachedVary and the PartialCachingCacheEntry rawResponse._cachedVaryId = cachedVary.CachedVaryId; } // Now insert into the cache (use cache provider if possible, otherwise use internal cache) if (!useProvider) { HttpRuntime.CacheInternal.UtcInsert(rawResponseKey, rawResponse, dependencies, absExp, slidingExp, CacheItemPriority.Normal, s_entryRemovedCallback); IncrementCount(); PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_ENTRIES); PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_TURNOVER_RATE); } else { string depKey = null; string[] fileDeps = null; if (dependencies != null) { depKey = OUTPUTCACHE_KEYPREFIX_DEPENDENCIES + dependencies.GetUniqueID(); fileDeps = dependencies.GetFileDependencies(); } OutputCacheEntry oce = Convert(rawResponse, depKey, fileDeps); provider.Set(rawResponseKey, oce, absExp); if (dependencies != null) { // use Add and dispose dependencies if there's already one in the cache Object d = HttpRuntime.CacheInternal.UtcAdd(depKey, new DependencyCacheEntry(rawResponseKey, oce.KernelCacheUrl, provider.Name), dependencies, absExp, Cache.NoSlidingExpiration, CacheItemPriority.Normal, s_dependencyRemovedCallback); if (d != null) { dependencies.Dispose(); } } } #if DBG string cachedVaryType = (cachedVaryPutInCache) ? "CachedVary" : ""; string providerUsed = (useProvider) ? provider.Name : "CacheInternal"; Debug.Trace("OutputCache", "InsertResposne(" + cachedVaryKey + ", " + cachedVaryType + ", " + rawResponseKey + ", CachedRawResponse, ...) -->" + providerUsed); #endif }
private static OutputCacheEntry Convert(CachedRawResponse cachedRawResponse, string depKey, string[] fileDependencies) { List<HeaderElement> headerElements = null; ArrayList headers = cachedRawResponse._rawResponse.Headers; int capacity = (headers != null) ? headers.Count : 0; for (int i = 0; i < capacity; i++) { if (headerElements == null) { headerElements = new List<HeaderElement>(capacity); } HttpResponseHeader header = (HttpResponseHeader) headers[i]; headerElements.Add(new HeaderElement(header.Name, header.Value)); } List<ResponseElement> responseElements = null; ArrayList buffers = cachedRawResponse._rawResponse.Buffers; capacity = (buffers != null) ? buffers.Count : 0; for (int j = 0; j < capacity; j++) { if (responseElements == null) { responseElements = new List<ResponseElement>(capacity); } IHttpResponseElement element = buffers[j] as IHttpResponseElement; if (element is HttpFileResponseElement) { HttpFileResponseElement element2 = element as HttpFileResponseElement; responseElements.Add(new FileResponseElement(element2.FileName, element2.Offset, element.GetSize())); } else if (element is HttpSubstBlockResponseElement) { HttpSubstBlockResponseElement element3 = element as HttpSubstBlockResponseElement; responseElements.Add(new SubstitutionResponseElement(element3.Callback)); } else { byte[] bytes = element.GetBytes(); long length = (bytes != null) ? ((long) bytes.Length) : ((long) 0); responseElements.Add(new MemoryResponseElement(bytes, length)); } } return new OutputCacheEntry(cachedRawResponse._cachedVaryId, cachedRawResponse._settings, cachedRawResponse._kernelCacheUrl, depKey, fileDependencies, cachedRawResponse._rawResponse.StatusCode, cachedRawResponse._rawResponse.StatusDescription, headerElements, responseElements); }
private static CachedRawResponse Convert(OutputCacheEntry oce) { ArrayList headers = null; if (oce.HeaderElements != null && oce.HeaderElements.Count > 0) { headers = new ArrayList(oce.HeaderElements.Count); for (int i = 0; i < oce.HeaderElements.Count; i++) { HttpResponseHeader h = new HttpResponseHeader(oce.HeaderElements[i].Name, oce.HeaderElements[i].Value); headers.Add(h); } } ArrayList buffers = null; if (oce.ResponseElements != null && oce.ResponseElements.Count > 0) { buffers = new ArrayList(oce.ResponseElements.Count); for (int i = 0; i < oce.ResponseElements.Count; i++) { ResponseElement re = oce.ResponseElements[i]; IHttpResponseElement elem = null; if (re is FileResponseElement) { HttpContext context = HttpContext.Current; HttpWorkerRequest wr = (context != null) ? context.WorkerRequest : null; bool supportsLongTransmitFile = (wr != null && wr.SupportsLongTransmitFile); bool isImpersonating = ((context != null && context.IsClientImpersonationConfigured) || HttpRuntime.IsOnUNCShareInternal); FileResponseElement fre = (FileResponseElement)re; // DevDiv #21203: Need to verify permission to access the requested file since handled by native code. HttpRuntime.CheckFilePermission(fre.Path); elem = new HttpFileResponseElement(fre.Path, fre.Offset, fre.Length, isImpersonating, supportsLongTransmitFile); } else if (re is MemoryResponseElement) { MemoryResponseElement mre = (MemoryResponseElement)re; int size = System.Convert.ToInt32(mre.Length); elem = new HttpResponseBufferElement(mre.Buffer, size); } else if (re is SubstitutionResponseElement) { SubstitutionResponseElement sre = (SubstitutionResponseElement)re; elem = new HttpSubstBlockResponseElement(sre.Callback); } else { throw new NotSupportedException(); } buffers.Add(elem); } } else { buffers = new ArrayList(); } HttpRawResponse rawResponse = new HttpRawResponse(oce.StatusCode, oce.StatusDescription, headers, buffers, false /*hasSubstBlocks*/); CachedRawResponse cachedRawResponse = new CachedRawResponse(rawResponse, oce.Settings, oce.KernelCacheUrl, oce.CachedVaryId); return(cachedRawResponse); }
internal static void InsertResponse(string cachedVaryKey, CachedVary cachedVary, string rawResponseKey, CachedRawResponse rawResponse, CacheDependency dependencies, DateTime absExp, TimeSpan slidingExp) { OutputCacheProvider provider = GetProvider(HttpContext.Current); bool flag = provider != null; if (flag) { bool flag2 = ((IsSubstBlockSerializable(rawResponse._rawResponse) && rawResponse._settings.IsValidationCallbackSerializable()) && (slidingExp == Cache.NoSlidingExpiration)) && ((dependencies == null) || dependencies.IsFileDependency()); if (flag && !flag2) { throw new ProviderException(System.Web.SR.GetString("Provider_does_not_support_policy_for_responses", new object[] { provider.Name })); } } if (cachedVary != null) { CachedVary vary; if (!flag) { vary = UtcAdd(cachedVaryKey, cachedVary); } else { vary = (CachedVary) provider.Add(cachedVaryKey, cachedVary, Cache.NoAbsoluteExpiration); } if (vary != null) { if (!cachedVary.Equals(vary)) { if (!flag) { HttpRuntime.CacheInternal.UtcInsert(cachedVaryKey, cachedVary); } else { provider.Set(cachedVaryKey, cachedVary, Cache.NoAbsoluteExpiration); } } else { cachedVary = vary; } } if (!flag) { AddCacheKeyToDependencies(ref dependencies, cachedVaryKey); } rawResponse._cachedVaryId = cachedVary.CachedVaryId; } if (!flag) { HttpRuntime.CacheInternal.UtcInsert(rawResponseKey, rawResponse, dependencies, absExp, slidingExp, CacheItemPriority.Normal, s_entryRemovedCallback); IncrementCount(); PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_ENTRIES); PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_TURNOVER_RATE); } else { string depKey = null; string[] fileDependencies = null; if (dependencies != null) { depKey = "aD" + dependencies.GetUniqueID(); fileDependencies = dependencies.GetFileDependencies(); } OutputCacheEntry entry = Convert(rawResponse, depKey, fileDependencies); provider.Set(rawResponseKey, entry, absExp); if ((dependencies != null) && (HttpRuntime.CacheInternal.UtcAdd(depKey, new DependencyCacheEntry(rawResponseKey, entry.KernelCacheUrl, provider.Name), dependencies, absExp, Cache.NoSlidingExpiration, CacheItemPriority.Normal, s_dependencyRemovedCallback) != null)) { dependencies.Dispose(); } } }
internal static void InsertResponse(string cachedVaryKey, CachedVary cachedVary, string rawResponseKey, CachedRawResponse rawResponse, CacheDependency dependencies, DateTime absExp, TimeSpan slidingExp) { OutputCacheProvider provider = GetProvider(HttpContext.Current); bool flag = provider != null; if (flag) { bool flag2 = ((IsSubstBlockSerializable(rawResponse._rawResponse) && rawResponse._settings.IsValidationCallbackSerializable()) && (slidingExp == Cache.NoSlidingExpiration)) && ((dependencies == null) || dependencies.IsFileDependency()); if (flag && !flag2) { throw new ProviderException(System.Web.SR.GetString("Provider_does_not_support_policy_for_responses", new object[] { provider.Name })); } } if (cachedVary != null) { CachedVary vary; if (!flag) { vary = UtcAdd(cachedVaryKey, cachedVary); } else { vary = (CachedVary)provider.Add(cachedVaryKey, cachedVary, Cache.NoAbsoluteExpiration); } if (vary != null) { if (!cachedVary.Equals(vary)) { if (!flag) { HttpRuntime.CacheInternal.UtcInsert(cachedVaryKey, cachedVary); } else { provider.Set(cachedVaryKey, cachedVary, Cache.NoAbsoluteExpiration); } } else { cachedVary = vary; } } if (!flag) { AddCacheKeyToDependencies(ref dependencies, cachedVaryKey); } rawResponse._cachedVaryId = cachedVary.CachedVaryId; } if (!flag) { HttpRuntime.CacheInternal.UtcInsert(rawResponseKey, rawResponse, dependencies, absExp, slidingExp, CacheItemPriority.Normal, s_entryRemovedCallback); IncrementCount(); PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_ENTRIES); PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_TURNOVER_RATE); } else { string depKey = null; string[] fileDependencies = null; if (dependencies != null) { depKey = "aD" + dependencies.GetUniqueID(); fileDependencies = dependencies.GetFileDependencies(); } OutputCacheEntry entry = Convert(rawResponse, depKey, fileDependencies); provider.Set(rawResponseKey, entry, absExp); if ((dependencies != null) && (HttpRuntime.CacheInternal.UtcAdd(depKey, new DependencyCacheEntry(rawResponseKey, entry.KernelCacheUrl, provider.Name), dependencies, absExp, Cache.NoSlidingExpiration, CacheItemPriority.Normal, s_dependencyRemovedCallback) != null)) { dependencies.Dispose(); } } }
/* * If the item is cacheable, add it to the cache. */ /// <devdoc> /// <para>Raises the <see langword='Leave'/> event, which causes any cacheable items to /// be put into the output cache.</para> /// </devdoc> internal /*public*/ void OnLeave(Object source, EventArgs eventArgs) { HttpApplication app; HttpContext context; bool cacheable; CachedVary cachedVary; HttpCachePolicy cache; HttpCachePolicySettings settings; string keyRawResponse; string[] varyByContentEncodings; string[] varyByHeaders; string[] varyByParams; bool varyByAllParams; HttpRequest request; HttpResponse response; int i, n; bool cacheAuthorizedPage; Debug.Trace("OutputCacheModuleLeave", "Beginning OutputCacheModule::Leave"); app = (HttpApplication)source; context = app.Context; request = context.Request; response = context.Response; cache = null; #if DBG string reason = null; #endif /* * Determine whether the response is cacheable. */ cacheable = false; do { if (!response.HasCachePolicy) { #if DBG reason = "CachePolicy not created, not modified from non-caching default."; #endif break; } cache = response.Cache; if (!cache.IsModified()) { #if DBG reason = "CachePolicy created, but not modified from non-caching default."; #endif break; } if (response.StatusCode != 200) { #if DBG reason = "response.StatusCode != 200."; #endif break; } if (request.HttpVerb != HttpVerb.GET && request.HttpVerb != HttpVerb.POST) { #if DBG reason = "the cache can only cache responses to GET and POST."; #endif break; } if (!response.IsBuffered()) { #if DBG reason = "the response is not buffered."; #endif break; } /* * Change a response with HttpCacheability.Public to HttpCacheability.Private * if it requires authorization, and allow it to be cached. * * Note that setting Cacheability to ServerAndPrivate would accomplish * the same thing without needing the "cacheAuthorizedPage" variable, * but in RTM we did not have ServerAndPrivate, and setting that value * would change the behavior. */ cacheAuthorizedPage = false; if ( cache.GetCacheability() == HttpCacheability.Public && context.RequestRequiresAuthorization()) { cache.SetCacheability(HttpCacheability.Private); cacheAuthorizedPage = true; } if ( cache.GetCacheability() != HttpCacheability.Public && cache.GetCacheability() != HttpCacheability.ServerAndPrivate && cache.GetCacheability() != HttpCacheability.ServerAndNoCache && !cacheAuthorizedPage) { #if DBG reason = "CachePolicy.Cacheability is not Public, ServerAndPrivate, or ServerAndNoCache."; #endif break; } if (cache.GetNoServerCaching()) { #if DBG reason = "CachePolicy.NoServerCaching is set."; #endif break; } // MSRC 11855 (DevDiv 297240 / 362405) - We should suppress output caching for responses which contain non-shareable cookies. // We already disable the HTTP.SYS and IIS user mode cache when *any* response cookie is present (see IIS7WorkerRequest.SendUnknownResponseHeader) if (response.ContainsNonShareableCookies()) { #if DBG reason = "Non-shareable response cookies were present."; #endif break; } if (!cache.HasExpirationPolicy() && !cache.HasValidationPolicy()) { #if DBG reason = "CachePolicy has no expiration policy or validation policy."; #endif break; } if (cache.VaryByHeaders.GetVaryByUnspecifiedParameters()) { #if DBG reason = "CachePolicy.Vary.VaryByUnspecifiedParameters was called."; #endif break; } if (!cache.VaryByParams.AcceptsParams() && (request.HttpVerb == HttpVerb.POST || request.HasQueryString)) { #if DBG reason = "the cache cannot cache responses to POSTs or GETs with query strings unless Cache.VaryByParams is modified."; #endif break; } if (cache.VaryByContentEncodings.IsModified() && !cache.VaryByContentEncodings.IsCacheableEncoding(context.Response.GetHttpHeaderContentEncoding())) { #if DBG reason = "the cache cannot cache encoded responses that are not listed in the VaryByContentEncodings collection."; #endif break; } cacheable = true; } while (false); /* * Add response to cache. */ if (!cacheable) { #if DBG Debug.Assert(reason != null, "reason != null"); Debug.Trace("OutputCacheModuleLeave", "Item is not output cacheable because " + reason + "\n\tUrl=" + request.Path + "\nReturning from OutputCacheModule::Leave"); #endif return; } RecordCacheMiss(); settings = cache.GetCurrentSettings(response); varyByContentEncodings = settings.VaryByContentEncodings; varyByHeaders = settings.VaryByHeaders; if (settings.IgnoreParams) { varyByParams = null; } else { varyByParams = settings.VaryByParams; } /* Create the key if it was not created in OnEnter */ if (_key == null) { _key = CreateOutputCachedItemKey(context, null); Debug.Assert(_key != null, "_key != null"); } if (varyByContentEncodings == null && varyByHeaders == null && varyByParams == null && settings.VaryByCustom == null) { /* * This is not a varyBy item. */ keyRawResponse = _key; cachedVary = null; } else { /* * There is a vary in the cache policy. We handle this * by adding another item to the cache which contains * a list of the vary headers. A request for the item * without the vary headers in the key will return this * item. From the headers another key can be constructed * to lookup the item with the raw response. */ if (varyByHeaders != null) { for (i = 0, n = varyByHeaders.Length; i < n; i++) { varyByHeaders[i] = "HTTP_" + CultureInfo.InvariantCulture.TextInfo.ToUpper( varyByHeaders[i].Replace('-', '_')); } } varyByAllParams = false; if (varyByParams != null) { varyByAllParams = (varyByParams.Length == 1 && varyByParams[0] == ASTERISK); if (varyByAllParams) { varyByParams = null; } else { for (i = 0, n = varyByParams.Length; i < n; i++) { varyByParams[i] = CultureInfo.InvariantCulture.TextInfo.ToLower(varyByParams[i]); } } } cachedVary = new CachedVary(varyByContentEncodings, varyByHeaders, varyByParams, varyByAllParams, settings.VaryByCustom); keyRawResponse = CreateOutputCachedItemKey(context, cachedVary); if (keyRawResponse == null) { Debug.Trace("OutputCacheModuleLeave", "Couldn't add non-cacheable post.\n\tkey=" + _key); return; } // it is possible that the user code calculating custom vary-by // string would Flush making the response non-cacheable. Check fo it here. if (!response.IsBuffered()) { Debug.Trace("OutputCacheModuleLeave", "Response.Flush() inside GetVaryByCustomString\n\tkey=" + _key); return; } } DateTime utcExpires = Cache.NoAbsoluteExpiration; TimeSpan slidingDelta = Cache.NoSlidingExpiration; if (settings.SlidingExpiration) { slidingDelta = settings.SlidingDelta; } else if (settings.IsMaxAgeSet) { DateTime utcTimestamp = (settings.UtcTimestampCreated != DateTime.MinValue) ? settings.UtcTimestampCreated : context.UtcTimestamp; utcExpires = utcTimestamp + settings.MaxAge; } else if (settings.IsExpiresSet) { utcExpires = settings.UtcExpires; } // Check and ensure that item hasn't expired: if (utcExpires > DateTime.UtcNow) { // Create the response object to be sent on cache hits. HttpRawResponse httpRawResponse = response.GetSnapshot(); string kernelCacheUrl = response.SetupKernelCaching(null); Guid cachedVaryId = (cachedVary != null) ? cachedVary.CachedVaryId : Guid.Empty; CachedRawResponse cachedRawResponse = new CachedRawResponse(httpRawResponse, settings, kernelCacheUrl, cachedVaryId); Debug.Trace("OutputCacheModuleLeave", "Adding response to cache.\n\tkey=" + keyRawResponse); CacheDependency dep = response.CreateCacheDependencyForResponse(); try { OutputCache.InsertResponse(_key, cachedVary, keyRawResponse, cachedRawResponse, dep, utcExpires, slidingDelta); } catch { if (dep != null) { dep.Dispose(); } throw; } } _key = null; Debug.Trace("OutputCacheModuleLeave", "Returning from OutputCacheModule::Leave"); }
private static CachedRawResponse Convert(OutputCacheEntry oce) { ArrayList headers = null; if (oce.HeaderElements != null && oce.HeaderElements.Count > 0) { headers = new ArrayList(oce.HeaderElements.Count); for (int i = 0; i < oce.HeaderElements.Count; i++) { HttpResponseHeader h = new HttpResponseHeader(oce.HeaderElements[i].Name, oce.HeaderElements[i].Value); headers.Add(h); } } ArrayList buffers = null; if (oce.ResponseElements != null && oce.ResponseElements.Count > 0) { buffers = new ArrayList(oce.ResponseElements.Count); for (int i = 0; i < oce.ResponseElements.Count; i++) { ResponseElement re = oce.ResponseElements[i]; IHttpResponseElement elem = null; if (re is FileResponseElement) { HttpContext context = HttpContext.Current; HttpWorkerRequest wr = (context != null) ? context.WorkerRequest : null; bool supportsLongTransmitFile = (wr != null && wr.SupportsLongTransmitFile); bool isImpersonating = ((context != null && context.IsClientImpersonationConfigured) || HttpRuntime.IsOnUNCShareInternal); FileResponseElement fre = (FileResponseElement)re; // DevDiv #21203: Need to verify permission to access the requested file since handled by native code. HttpRuntime.CheckFilePermission(fre.Path); elem = new HttpFileResponseElement(fre.Path, fre.Offset, fre.Length, isImpersonating, supportsLongTransmitFile); } else if (re is MemoryResponseElement) { MemoryResponseElement mre = (MemoryResponseElement)re; int size = System.Convert.ToInt32(mre.Length); elem = new HttpResponseBufferElement(mre.Buffer, size); } else if (re is SubstitutionResponseElement) { SubstitutionResponseElement sre = (SubstitutionResponseElement)re; elem = new HttpSubstBlockResponseElement(sre.Callback); } else { throw new NotSupportedException(); } buffers.Add(elem); } } else { buffers = new ArrayList(); } HttpRawResponse rawResponse = new HttpRawResponse(oce.StatusCode, oce.StatusDescription, headers, buffers, false /*hasSubstBlocks*/); CachedRawResponse cachedRawResponse = new CachedRawResponse(rawResponse, oce.Settings, oce.KernelCacheUrl, oce.CachedVaryId); return cachedRawResponse; }
/* * If the item is cacheable, add it to the cache. */ /// <include file='doc\OutputCacheModule.uex' path='docs/doc[@for="OutputCacheModule.OnLeave"]/*' /> /// <devdoc> /// <para>Raises the <see langword='Leave'/> event, which causes any cacheable items to /// be put into the output cache.</para> /// </devdoc> internal /*public*/ void OnLeave(Object source, EventArgs eventArgs) { HttpApplication app; HttpContext context; bool cacheable; CachedRawResponse cachedRawResponse; CachedVary cachedVary; CachedVary cachedVaryInCache; HttpCachePolicy cache; HttpCachePolicySettings settings; CacheDependency dependency; CacheDependency dependencyVary; string keyRawResponse; string[] varyByHeaders; string[] varyByParams; bool varyByAllParams; HttpRequest request; HttpResponse response; DateTime utcTimestamp; TimeSpan slidingDelta; HttpRawResponse httpRawResponse; int i, n; DateTime utcExpires; bool cacheAuthorizedPage; CacheInternal cacheInternal; Debug.Trace("OutputCacheModuleLeave", "Beginning OutputCacheModule::Leave"); app = (HttpApplication)source; context = app.Context; request = context.Request; response = context.Response; cache = response.Cache; #if DBG string reason = null; #endif /* * Determine whether the response is cacheable. */ cacheable = false; do { if (!cache.IsModified()) { #if DBG reason = "CachePolicy was not modified from non-caching default."; #endif break; } if (_key == null) { #if DBG reason = "no key was created for Request in Enter method."; #endif break; } if (response.StatusCode != 200) { #if DBG reason = "response.StatusCode != 200."; #endif break; } if (_method == CacheRequestMethod.Head) { #if DBG reason = "the cache cannot cache responses to HEAD requests."; #endif break; } if (!response.IsBuffered()) { #if DBG reason = "the response is not buffered."; #endif break; } /* * Change a response with HttpCacheability.Public to HttpCacheability.Private * if it requires authorization, and allow it to be cached. * * Note that setting Cacheability to ServerAndPrivate would accomplish * the same thing without needing the "cacheAuthorizedPage" variable, * but in RTM we did not have ServerAndPrivate, and setting that value * would change the behavior. */ cacheAuthorizedPage = false; if (cache.GetCacheability() == HttpCacheability.Public && context.RequestRequiresAuthorization()) { cache.SetCacheability(HttpCacheability.Private); cacheAuthorizedPage = true; } if (cache.GetCacheability() != HttpCacheability.Public && cache.GetCacheability() != HttpCacheability.ServerAndPrivate && cache.GetCacheability() != HttpCacheability.ServerAndNoCache && !cacheAuthorizedPage) { #if DBG reason = "CachePolicy.Cacheability is not Public, ServerAndPrivate, or ServerAndNoCache."; #endif break; } if (cache.GetNoServerCaching()) { #if DBG reason = "CachePolicy.NoServerCaching is set."; #endif break; } if (!cache.HasExpirationPolicy() && !cache.HasValidationPolicy()) { #if DBG reason = "CachePolicy has no expiration policy or validation policy."; #endif break; } if (cache.VaryByHeaders.GetVaryByUnspecifiedParameters()) { #if DBG reason = "CachePolicy.Vary.VaryByUnspecifiedParameters was called."; #endif break; } if (!cache.VaryByParams.AcceptsParams() && (_method == CacheRequestMethod.Post || request.QueryStringText != String.Empty)) { #if DBG reason = "the cache cannot cache responses to POSTs or GETs with query strings unless Cache.VaryByParams is modified."; #endif break; } cacheable = true; } while (false); /* * Add response to cache. */ if (!cacheable) { #if DBG Debug.Assert(reason != null, "reason != null"); Debug.Trace("OutputCacheModuleLeave", "Item is not output cacheable because " + reason + "\n\tUrl=" + request.Url.ToString() + "\nReturning from OutputCacheModule::Leave"); #endif return; } RecordCacheMiss(); settings = cache.GetCurrentSettings(response); /* Determine the size of the sliding expiration.*/ utcTimestamp = context.UtcTimestamp; utcExpires = DateTime.MaxValue; if (settings.SlidingExpiration) { slidingDelta = settings.SlidingDelta; utcExpires = Cache.NoAbsoluteExpiration; } else { slidingDelta = Cache.NoSlidingExpiration; if (settings.IsMaxAgeSet) { utcExpires = utcTimestamp + settings.MaxAge; } else if (settings.IsExpiresSet) { utcExpires = settings.UtcExpires; } } varyByHeaders = settings.VaryByHeaders; if (settings.IgnoreParams) { varyByParams = null; } else { varyByParams = settings.VaryByParams; } cacheInternal = HttpRuntime.CacheInternal; if (varyByHeaders == null && varyByParams == null && settings.VaryByCustom == null) { /* * This is not a varyBy item. */ keyRawResponse = _key; cachedVary = null; dependencyVary = null; } else { /* * There is a vary in the cache policy. We handle this * by adding another item to the cache which contains * a list of the vary headers. A request for the item * without the vary headers in the key will return this * item. From the headers another key can be constructed * to lookup the item with the raw response. */ if (varyByHeaders != null) { for (i = 0, n = varyByHeaders.Length; i < n; i++) { varyByHeaders[i] = "HTTP_" + CultureInfo.InvariantCulture.TextInfo.ToUpper( varyByHeaders[i].Replace('-', '_')); } } varyByAllParams = false; if (varyByParams != null) { varyByAllParams = (varyByParams.Length == 1 && varyByParams[0] == "*"); if (varyByAllParams) { varyByParams = null; } else { for (i = 0, n = varyByParams.Length; i < n; i++) { varyByParams[i] = CultureInfo.InvariantCulture.TextInfo.ToLower(varyByParams[i]); } } } cachedVary = new CachedVary(varyByHeaders, varyByParams, varyByAllParams, settings.VaryByCustom); keyRawResponse = CreateOutputCachedItemKey(context, cachedVary); if (keyRawResponse == null) { Debug.Trace("OutputCacheModuleLeave", "Couldn't add non-cacheable post.\n\tkey=" + _key); return; } // it is possible that the user code calculating custom vary-by // string would Flush making the response non-cacheable. Check fo it here. if (!response.IsBuffered()) { Debug.Trace("OutputCacheModuleLeave", "Response.Flush() inside GetVaryByCustomString\n\tkey=" + _key); return; } /* * Add the CachedVary item so that a request will know * which headers are needed to issue another request. * * Use the Add method so that we guarantee we only use * a single CachedVary and don't overwrite existing ones. */ cachedVaryInCache = (CachedVary)cacheInternal.UtcAdd( _key, cachedVary, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Default, null); if (cachedVaryInCache != null) { if (cachedVary.Equals(cachedVaryInCache)) { cachedVary = cachedVaryInCache; } else { Debug.Trace("OutputCacheModuleLeave", "CachedVary definition changed, new CachedVary inserted into cache.\n\tkey=" + _key); cacheInternal.UtcInsert(_key, cachedVary); } } #if DBG else { Debug.Trace("OutputCacheModuleLeave", "Added CachedVary to cache.\n\tkey=" + _key); } #endif dependencyVary = new CacheDependency(false, null, new string[1] { _key }); } Debug.Trace("OutputCacheModuleLeave", "Adding response to cache.\n\tkey=" + keyRawResponse + "\nReturning from OutputCacheModule::Leave"); dependency = response.GetCacheDependency(dependencyVary); /* * Create the response object to be sent on cache hits. */ httpRawResponse = response.GetSnapshot(); cachedRawResponse = new CachedRawResponse(httpRawResponse, settings, cachedVary); Debug.Trace("OutputCacheModuleLeave", "utcExpires=" + utcExpires + "expires=" + DateTimeUtil.ConvertToLocalTime(utcExpires)); cacheInternal.UtcInsert( keyRawResponse, cachedRawResponse, dependency, utcExpires, slidingDelta, CacheItemPriority.Normal, s_cacheItemRemovedCallback); PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_ENTRIES); PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_TURNOVER_RATE); }
void DoCacheInsert(HttpContext context, HttpApplication app, HttpResponse response) { string vary_key = context.Request.FilePath; string key; OutputCacheProvider provider = FindCacheProvider(app); CachedVaryBy varyby = provider.Get(vary_key) as CachedVaryBy; CachedRawResponse prev = null; bool lookup = true; string cacheKey = null, cacheValue = null; HttpCachePolicy cachePolicy = response.Cache; if (varyby == null) { varyby = new CachedVaryBy(cachePolicy, vary_key); provider.Add(vary_key, varyby, Cache.NoAbsoluteExpiration); lookup = false; cacheKey = vary_key; } key = varyby.CreateKey(vary_key, context); if (lookup) { prev = provider.Get(key) as CachedRawResponse; } if (prev == null) { CachedRawResponse c = response.GetCachedResponse(); if (c != null) { string [] keys = new string [] { vary_key }; DateTime utcExpiry, absoluteExpiration; TimeSpan slidingExpiration; c.VaryBy = varyby; varyby.ItemList.Add(key); if (cachePolicy.Sliding) { slidingExpiration = TimeSpan.FromSeconds(cachePolicy.Duration); absoluteExpiration = Cache.NoAbsoluteExpiration; utcExpiry = DateTime.UtcNow + slidingExpiration; } else { slidingExpiration = Cache.NoSlidingExpiration; absoluteExpiration = cachePolicy.Expires; utcExpiry = absoluteExpiration.ToUniversalTime(); } provider.Set(key, c, utcExpiry); HttpRuntime.InternalCache.Insert(key, c, new CacheDependency(null, keys), absoluteExpiration, slidingExpiration, CacheItemPriority.Normal, response_removed); cacheValue = key; } } if (cacheKey != null) { lock (keysCacheLock) { if (keysCache == null) { BuildManager.RemoveEntry += new BuildManagerRemoveEntryEventHandler(OnBuildManagerRemoveEntry); keysCache = new Dictionary <string, string> (StringComparer.Ordinal); keysCache.Add(cacheKey, cacheValue); } else if (!keysCache.ContainsKey(cacheKey)) { keysCache.Add(cacheKey, cacheValue); } } } }
internal void OnLeave(object source, EventArgs eventArgs) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; HttpRequest request = context.Request; HttpResponse response = context.Response; HttpCachePolicy cache = null; bool flag = false; if (response.HasCachePolicy) { cache = response.Cache; if (((cache.IsModified() && (response.Cookies.Count <= 0)) && (response.StatusCode == 200)) && (((request.HttpVerb == HttpVerb.GET) || (request.HttpVerb == HttpVerb.POST)) && response.IsBuffered())) { bool flag3 = false; if ((cache.GetCacheability() == HttpCacheability.Public) && context.RequestRequiresAuthorization()) { cache.SetCacheability(HttpCacheability.Private); flag3 = true; } if (((((cache.GetCacheability() == HttpCacheability.Public) || (cache.GetCacheability() == HttpCacheability.ServerAndPrivate)) || ((cache.GetCacheability() == HttpCacheability.Server) || flag3)) && (!cache.GetNoServerCaching() && (cache.HasExpirationPolicy() || cache.HasValidationPolicy()))) && ((!cache.VaryByHeaders.GetVaryByUnspecifiedParameters() && (cache.VaryByParams.AcceptsParams() || ((request.HttpVerb != HttpVerb.POST) && !request.HasQueryString))) && (!cache.VaryByContentEncodings.IsModified() || cache.VaryByContentEncodings.IsCacheableEncoding(context.Response.GetHttpHeaderContentEncoding())))) { flag = true; } } } if (flag) { CachedVary vary; string str; string[] varyByParams; this.RecordCacheMiss(); HttpCachePolicySettings currentSettings = cache.GetCurrentSettings(response); string[] varyByContentEncodings = currentSettings.VaryByContentEncodings; string[] varyByHeaders = currentSettings.VaryByHeaders; if (currentSettings.IgnoreParams) { varyByParams = null; } else { varyByParams = currentSettings.VaryByParams; } if (this._key == null) { this._key = this.CreateOutputCachedItemKey(context, null); } if (((varyByContentEncodings == null) && (varyByHeaders == null)) && ((varyByParams == null) && (currentSettings.VaryByCustom == null))) { str = this._key; vary = null; } else { int num; int length; if (varyByHeaders != null) { num = 0; length = varyByHeaders.Length; while (num < length) { varyByHeaders[num] = "HTTP_" + CultureInfo.InvariantCulture.TextInfo.ToUpper(varyByHeaders[num].Replace('-', '_')); num++; } } bool varyByAllParams = false; if (varyByParams != null) { varyByAllParams = (varyByParams.Length == 1) && (varyByParams[0] == "*"); if (varyByAllParams) { varyByParams = null; } else { num = 0; length = varyByParams.Length; while (num < length) { varyByParams[num] = CultureInfo.InvariantCulture.TextInfo.ToLower(varyByParams[num]); num++; } } } vary = new CachedVary(varyByContentEncodings, varyByHeaders, varyByParams, varyByAllParams, currentSettings.VaryByCustom); str = this.CreateOutputCachedItemKey(context, vary); if (str == null) { return; } if (!response.IsBuffered()) { return; } } DateTime noAbsoluteExpiration = Cache.NoAbsoluteExpiration; TimeSpan noSlidingExpiration = Cache.NoSlidingExpiration; if (currentSettings.SlidingExpiration) { noSlidingExpiration = currentSettings.SlidingDelta; } else if (currentSettings.IsMaxAgeSet) { DateTime time2 = (currentSettings.UtcTimestampCreated != DateTime.MinValue) ? currentSettings.UtcTimestampCreated : context.UtcTimestamp; noAbsoluteExpiration = time2 + currentSettings.MaxAge; } else if (currentSettings.IsExpiresSet) { noAbsoluteExpiration = currentSettings.UtcExpires; } if (noAbsoluteExpiration > DateTime.UtcNow) { HttpRawResponse snapshot = response.GetSnapshot(); string kernelCacheUrl = response.SetupKernelCaching(null); Guid cachedVaryId = (vary != null) ? vary.CachedVaryId : Guid.Empty; CachedRawResponse rawResponse = new CachedRawResponse(snapshot, currentSettings, kernelCacheUrl, cachedVaryId); CacheDependency dependencies = response.CreateCacheDependencyForResponse(); try { OutputCache.InsertResponse(this._key, vary, str, rawResponse, dependencies, noAbsoluteExpiration, noSlidingExpiration); } catch { if (dependencies != null) { dependencies.Dispose(); } throw; } } this._key = null; } }
internal void OnEnter(object source, EventArgs eventArgs) { this._key = null; this._recordedCacheMiss = false; if (OutputCache.InUse) { string[] strArray2 = null; string[] strArray3 = null; HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.GetFilePathData(); HttpRequest request = context.Request; HttpResponse response = context.Response; switch (request.HttpVerb) { case HttpVerb.GET: case HttpVerb.HEAD: case HttpVerb.POST: { string str; this._key = str = this.CreateOutputCachedItemKey(context, null); object obj2 = OutputCache.Get(str); if (obj2 != null) { int num; int length; CachedVary cachedVary = obj2 as CachedVary; if (cachedVary != null) { str = this.CreateOutputCachedItemKey(context, cachedVary); if (str == null) { return; } if (cachedVary._contentEncodings == null) { obj2 = OutputCache.Get(str); } else { obj2 = null; bool flag3 = true; string knownRequestHeader = context.WorkerRequest.GetKnownRequestHeader(0x16); if (knownRequestHeader != null) { string[] contentEncodings = cachedVary._contentEncodings; int startIndex = 0; bool flag4 = false; while (!flag4) { flag4 = true; int index = GetAcceptableEncoding(contentEncodings, startIndex, knownRequestHeader); if (index > -1) { flag3 = false; obj2 = OutputCache.Get(str + contentEncodings[index]); if (obj2 == null) { startIndex = index + 1; if (startIndex < contentEncodings.Length) { flag4 = false; } } } else if (index == -2) { flag3 = false; } } } if ((obj2 == null) && flag3) { obj2 = OutputCache.Get(str); } } if ((obj2 == null) || (((CachedRawResponse)obj2)._cachedVaryId != cachedVary.CachedVaryId)) { if (obj2 != null) { OutputCache.Remove(str, context); } return; } } CachedRawResponse response2 = (CachedRawResponse)obj2; HttpCachePolicySettings settings = response2._settings; if ((cachedVary == null) && !settings.IgnoreParams) { if (request.HttpVerb == HttpVerb.POST) { this.RecordCacheMiss(); return; } if (request.HasQueryString) { this.RecordCacheMiss(); return; } } if (settings.IgnoreRangeRequests) { string str8 = request.Headers["Range"]; if (StringUtil.StringStartsWithIgnoreCase(str8, "bytes")) { return; } } if (!settings.HasValidationPolicy()) { string str4 = request.Headers["Cache-Control"]; if (str4 != null) { strArray2 = str4.Split(s_fieldSeparators); for (num = 0; num < strArray2.Length; num++) { string str6 = strArray2[num]; switch (str6) { case "no-cache": case "no-store": this.RecordCacheMiss(); return; } if (StringUtil.StringStartsWith(str6, "max-age=")) { int num4; try { num4 = Convert.ToInt32(str6.Substring(8), CultureInfo.InvariantCulture); } catch { num4 = -1; } if (num4 >= 0) { int num6 = (int)((context.UtcTimestamp.Ticks - settings.UtcTimestampCreated.Ticks) / 0x989680L); if (num6 >= num4) { this.RecordCacheMiss(); return; } } } else if (StringUtil.StringStartsWith(str6, "min-fresh=")) { int num5; try { num5 = Convert.ToInt32(str6.Substring(10), CultureInfo.InvariantCulture); } catch { num5 = -1; } if (((num5 >= 0) && settings.IsExpiresSet) && !settings.SlidingExpiration) { int num7 = (int)((settings.UtcExpires.Ticks - context.UtcTimestamp.Ticks) / 0x989680L); if (num7 < num5) { this.RecordCacheMiss(); return; } } } } } string str5 = request.Headers["Pragma"]; if (str5 != null) { strArray3 = str5.Split(s_fieldSeparators); for (num = 0; num < strArray3.Length; num++) { if (strArray3[num] == "no-cache") { this.RecordCacheMiss(); return; } } } } else if (settings.ValidationCallbackInfo != null) { HttpValidationStatus valid = HttpValidationStatus.Valid; HttpValidationStatus ignoreThisRequest = valid; num = 0; length = settings.ValidationCallbackInfo.Length; while (num < length) { ValidationCallbackInfo info = settings.ValidationCallbackInfo[num]; try { info.handler(context, info.data, ref valid); } catch (Exception exception) { valid = HttpValidationStatus.Invalid; HttpApplicationFactory.RaiseError(exception); } switch (valid) { case HttpValidationStatus.Invalid: OutputCache.Remove(str, context); this.RecordCacheMiss(); return; case HttpValidationStatus.IgnoreThisRequest: ignoreThisRequest = HttpValidationStatus.IgnoreThisRequest; break; case HttpValidationStatus.Valid: break; default: valid = ignoreThisRequest; break; } num++; } if (ignoreThisRequest == HttpValidationStatus.IgnoreThisRequest) { this.RecordCacheMiss(); return; } } HttpRawResponse rawResponse = response2._rawResponse; if ((cachedVary == null) || (cachedVary._contentEncodings == null)) { string acceptEncoding = request.Headers["Accept-Encoding"]; string contentEncoding = null; ArrayList headers = rawResponse.Headers; if (headers != null) { foreach (HttpResponseHeader header in headers) { if (header.Name == "Content-Encoding") { contentEncoding = header.Value; break; } } } if (!IsAcceptableEncoding(contentEncoding, acceptEncoding)) { this.RecordCacheMiss(); return; } } int num3 = -1; if (!rawResponse.HasSubstBlocks) { string ifModifiedSince = request.IfModifiedSince; if (ifModifiedSince != null) { num3 = 0; try { DateTime time = HttpDate.UtcParse(ifModifiedSince); if ((settings.IsLastModifiedSet && (settings.UtcLastModified <= time)) && (time <= context.UtcTimestamp)) { num3 = 1; } } catch { } } if (num3 != 0) { string ifNoneMatch = request.IfNoneMatch; if (ifNoneMatch != null) { num3 = 0; string[] strArray = ifNoneMatch.Split(s_fieldSeparators); num = 0; length = strArray.Length; while (num < length) { if ((num == 0) && strArray[num].Equals("*")) { num3 = 1; break; } if (strArray[num].Equals(settings.ETag)) { num3 = 1; break; } num++; } } } } if (num3 == 1) { response.ClearAll(); response.StatusCode = 0x130; } else { bool sendBody = request.HttpVerb != HttpVerb.HEAD; response.UseSnapshot(rawResponse, sendBody); } response.Cache.ResetFromHttpCachePolicySettings(settings, context.UtcTimestamp); string originalCacheUrl = response2._kernelCacheUrl; if (originalCacheUrl != null) { response.SetupKernelCaching(originalCacheUrl); } PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_RATIO_BASE); PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_HITS); this._key = null; this._recordedCacheMiss = false; application.CompleteRequest(); return; } return; } } } }
private static OutputCacheEntry Convert(CachedRawResponse cachedRawResponse, string depKey, string[] fileDependencies) { List<HeaderElement> headerElements = null; ArrayList headers = cachedRawResponse._rawResponse.Headers; int count = (headers != null) ? headers.Count : 0; for (int i = 0; i < count; i++) { if (headerElements == null) { headerElements = new List<HeaderElement>(count); } HttpResponseHeader h = (HttpResponseHeader)(headers[i]); headerElements.Add(new HeaderElement(h.Name, h.Value)); } List<ResponseElement> responseElements = null; ArrayList buffers = cachedRawResponse._rawResponse.Buffers; count = (buffers != null) ? buffers.Count : 0; for (int i = 0; i < count; i++) { if (responseElements == null) { responseElements = new List<ResponseElement>(count); } IHttpResponseElement elem = buffers[i] as IHttpResponseElement; if (elem is HttpFileResponseElement) { HttpFileResponseElement fileElement = elem as HttpFileResponseElement; responseElements.Add(new FileResponseElement(fileElement.FileName, fileElement.Offset, elem.GetSize())); } else if (elem is HttpSubstBlockResponseElement) { HttpSubstBlockResponseElement substElement = elem as HttpSubstBlockResponseElement; responseElements.Add(new SubstitutionResponseElement(substElement.Callback)); } else { byte[] b = elem.GetBytes(); long length = (b != null) ? b.Length : 0; responseElements.Add(new MemoryResponseElement(b, length)); } } OutputCacheEntry oce = new OutputCacheEntry( cachedRawResponse._cachedVaryId, cachedRawResponse._settings, cachedRawResponse._kernelCacheUrl, depKey, fileDependencies, cachedRawResponse._rawResponse.StatusCode, cachedRawResponse._rawResponse.StatusDescription, headerElements, responseElements ); return oce; }
private void OnCacheabilityUpdated (object sender, CacheabilityUpdatedEventArgs e) { if (e.Cacheability >= HttpCacheability.Server && !IsCached) cached_response = new CachedRawResponse (_CachePolicy); else if (e.Cacheability <= HttpCacheability.Private) cached_response = null; }
// insert cached vary or output cache entry internal static void InsertResponse(String cachedVaryKey, CachedVary cachedVary, String rawResponseKey, CachedRawResponse rawResponse, CacheDependency dependencies, DateTime absExp, TimeSpan slidingExp) { // if the provider is undefined or the fragment can't be inserted in the // provider, insert it in the internal cache. OutputCacheProvider provider = GetProvider(HttpContext.Current); // // CachedVary can be serialized. // CachedRawResponse is not always serializable. // bool useProvider = (provider != null); if (useProvider) { bool canUseProvider = (IsSubstBlockSerializable(rawResponse._rawResponse) && rawResponse._settings.IsValidationCallbackSerializable() && slidingExp == Cache.NoSlidingExpiration && (dependencies == null || dependencies.IsFileDependency())); if (useProvider && !canUseProvider) { throw new ProviderException(SR.GetString(SR.Provider_does_not_support_policy_for_responses, provider.Name)); } } #if DBG bool cachedVaryPutInCache = (cachedVary != null); #endif if (cachedVary != null) { /* * Add the CachedVary item so that a request will know * which headers are needed to issue another request. * * Use the Add method so that we guarantee we only use * a single CachedVary and don't overwrite existing ones. */ CachedVary cachedVaryInCache; if (!useProvider) { cachedVaryInCache = OutputCache.UtcAdd(cachedVaryKey, cachedVary); } else { cachedVaryInCache = (CachedVary) provider.Add(cachedVaryKey, cachedVary, Cache.NoAbsoluteExpiration); } if (cachedVaryInCache != null) { if (!cachedVary.Equals(cachedVaryInCache)) { if (!useProvider) { HttpRuntime.CacheInternal.UtcInsert(cachedVaryKey, cachedVary); } else { provider.Set(cachedVaryKey, cachedVary, Cache.NoAbsoluteExpiration); } } else { cachedVary = cachedVaryInCache; #if DBG cachedVaryPutInCache = false; #endif } } if (!useProvider) { AddCacheKeyToDependencies(ref dependencies, cachedVaryKey); } // not all caches support cache key dependencies, but we can use a "change number" to associate // the ControlCachedVary and the PartialCachingCacheEntry rawResponse._cachedVaryId = cachedVary.CachedVaryId; } // Now insert into the cache (use cache provider if possible, otherwise use internal cache) if (!useProvider) { HttpRuntime.CacheInternal.UtcInsert(rawResponseKey, rawResponse, dependencies, absExp, slidingExp, CacheItemPriority.Normal, s_entryRemovedCallback); IncrementCount(); PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_ENTRIES); PerfCounters.IncrementCounter(AppPerfCounter.OUTPUT_CACHE_TURNOVER_RATE); } else { string depKey = null; string[] fileDeps = null; if (dependencies != null) { depKey = OUTPUTCACHE_KEYPREFIX_DEPENDENCIES + dependencies.GetUniqueID(); fileDeps = dependencies.GetFileDependencies(); } OutputCacheEntry oce = Convert(rawResponse, depKey, fileDeps); provider.Set(rawResponseKey, oce, absExp); if (dependencies != null) { // use Add and dispose dependencies if there's already one in the cache Object d = HttpRuntime.CacheInternal.UtcAdd(depKey, new DependencyCacheEntry(rawResponseKey, oce.KernelCacheUrl, provider.Name), dependencies, absExp, Cache.NoSlidingExpiration, CacheItemPriority.Normal, s_dependencyRemovedCallback); if (d != null) { dependencies.Dispose(); } } } #if DBG string cachedVaryType = (cachedVaryPutInCache) ? "CachedVary" : ""; string providerUsed = (useProvider) ? provider.Name : "CacheInternal"; Debug.Trace("OutputCache", "InsertResposne(" + cachedVaryKey + ", " + cachedVaryType + ", " + rawResponseKey + ", CachedRawResponse, ...) -->" + providerUsed); #endif }
void DoCacheInsert(HttpContext context) { string vary_key = context.Request.FilePath; string key; CachedVaryBy varyby = context.Cache [vary_key] as CachedVaryBy; CachedRawResponse prev = null; bool lookup = true; #if NET_2_0 string cacheKey = null, cacheValue = null; #endif if (varyby == null) { string path = context.Request.MapPath(vary_key); string [] files = new string [] { path }; string [] keys = new string [0]; varyby = new CachedVaryBy(context.Response.Cache, vary_key); context.Cache.Insert(vary_key, varyby, new CacheDependency(files, keys), Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); lookup = false; #if NET_2_0 cacheKey = vary_key; #endif } key = varyby.CreateKey(vary_key, context); if (lookup) { prev = context.InternalCache [key] as CachedRawResponse; } if (prev == null) { CachedRawResponse c = context.Response.GetCachedResponse(); if (c != null) { string [] files = new string [] { }; string [] keys = new string [] { vary_key }; bool sliding = context.Response.Cache.Sliding; context.InternalCache.Insert(key, c, new CacheDependency(files, keys), (sliding ? Cache.NoAbsoluteExpiration : context.Response.Cache.Expires), (sliding ? TimeSpan.FromSeconds( context.Response.Cache.Duration) : Cache.NoSlidingExpiration), CacheItemPriority.Normal, response_removed); c.VaryBy = varyby; varyby.ItemList.Add(key); #if NET_2_0 cacheValue = key; #endif } } #if NET_2_0 if (cacheKey != null) { lock (keysCacheLock) { if (keysCache == null) { BuildManager.RemoveEntry += new BuildManagerRemoveEntryEventHandler(OnBuildManagerRemoveEntry); keysCache = new Dictionary <string, string> (StringComparer.Ordinal); keysCache.Add(cacheKey, cacheValue); } else if (!keysCache.ContainsKey(cacheKey)) { keysCache.Add(cacheKey, cacheValue); } } } #endif }