public virtual bool AllowCacheLookup(ResponseCachingContext context) { var requestHeaders = context.HttpContext.Request.Headers; var cacheControl = requestHeaders.CacheControl; // Verify request cache-control parameters if (!StringValues.IsNullOrEmpty(cacheControl)) { if (HeaderUtilities.ContainsCacheDirective(cacheControl, CacheControlHeaderValue.NoCacheString)) { context.Logger.RequestWithNoCacheNotCacheable(); return(false); } } else { // Support for legacy HTTP 1.0 cache directive if (HeaderUtilities.ContainsCacheDirective(requestHeaders.Pragma, CacheControlHeaderValue.NoCacheString)) { context.Logger.RequestWithPragmaNoCacheNotCacheable(); return(false); } } return(true); }
public bool AllowCacheLookup(ResponseCachingContext context) { var req = context.HttpContext.Request; // cache-control: nocache ? if (HeaderUtilities.ContainsCacheDirective(req.Headers[HeaderNames.CacheControl], CacheControlHeaderValue.NoCacheString)) { return(false); } // return(true); }
static bool IsResponseCacheable(HttpContext context) { var responseCacheControlHeader = context.Response.Headers[HeaderNames.CacheControl]; // Check response no-store if (HeaderUtilities.ContainsCacheDirective(responseCacheControlHeader, CacheControlHeaderValue.NoStoreString)) { return(false); } // Check no-cache if (HeaderUtilities.ContainsCacheDirective(responseCacheControlHeader, CacheControlHeaderValue.NoCacheString)) { return(false); } var response = context.Response; // Do not cache responses with Set-Cookie headers if (!StringValues.IsNullOrEmpty(response.Headers[HeaderNames.SetCookie])) { return(false); } // Do not cache responses varying by * var varyHeader = response.Headers[HeaderNames.Vary]; if (varyHeader.Count == 1 && string.Equals(varyHeader, "*", StringComparison.OrdinalIgnoreCase)) { return(false); } // Check private if (HeaderUtilities.ContainsCacheDirective(responseCacheControlHeader, CacheControlHeaderValue.PrivateString)) { return(false); } // Check response code if (response.StatusCode != StatusCodes.Status200OK) { return(false); } // // // context.Response.Headers[HeaderNames.CacheControl] = StringValues.Concat(CacheControlHeaderValue.SharedMaxAgeString + "=" + 60*60, responseCacheControlHeader); // return(true); }
static bool AllowCacheLookup(HttpContext context) { var req = context.Request; // cache-control: nocache ? if (HeaderUtilities.ContainsCacheDirective(req.Headers[HeaderNames.CacheControl], CacheControlHeaderValue.NoCacheString)) { return(false); } // logged user or posting comment: if (req.Cookies.Any(CookieDisallowsCaching)) { return(false); } // return(true); }
internal async Task <bool> TryServeFromCacheAsync(ResponseCachingContext context) { context.BaseKey = _keyProvider.CreateBaseKey(context); var cacheEntry = await _cache.GetAsync(context.BaseKey); var cachedVaryByRules = cacheEntry as CachedVaryByRules; if (cachedVaryByRules != null) { // Request contains vary rules, recompute key(s) and try again context.CachedVaryByRules = cachedVaryByRules; foreach (var varyKey in _keyProvider.CreateLookupVaryByKeys(context)) { if (await TryServeCachedResponseAsync(context, await _cache.GetAsync(varyKey))) { return(true); } } } else { if (await TryServeCachedResponseAsync(context, cacheEntry)) { return(true); } } if (HeaderUtilities.ContainsCacheDirective(context.HttpContext.Request.Headers[HeaderNames.CacheControl], CacheControlHeaderValue.OnlyIfCachedString)) { _logger.LogGatewayTimeoutServed(); context.HttpContext.Response.StatusCode = StatusCodes.Status504GatewayTimeout; return(true); } _logger.LogNoResponseServed(); return(false); }
public virtual bool IsResponseCacheable(ResponseCachingContext context) { var responseCacheControlHeader = context.HttpContext.Response.Headers.CacheControl; // Only cache pages explicitly marked with public if (!HeaderUtilities.ContainsCacheDirective(responseCacheControlHeader, CacheControlHeaderValue.PublicString)) { context.Logger.ResponseWithoutPublicNotCacheable(); return(false); } // Check response no-store if (HeaderUtilities.ContainsCacheDirective(responseCacheControlHeader, CacheControlHeaderValue.NoStoreString)) { context.Logger.ResponseWithNoStoreNotCacheable(); return(false); } // Check no-cache if (HeaderUtilities.ContainsCacheDirective(responseCacheControlHeader, CacheControlHeaderValue.NoCacheString)) { context.Logger.ResponseWithNoCacheNotCacheable(); return(false); } var response = context.HttpContext.Response; // Do not cache responses with Set-Cookie headers if (!StringValues.IsNullOrEmpty(response.Headers.SetCookie)) { context.Logger.ResponseWithSetCookieNotCacheable(); return(false); } // Do not cache responses varying by * var varyHeader = response.Headers.Vary; if (varyHeader.Count == 1 && string.Equals(varyHeader, "*", StringComparison.OrdinalIgnoreCase)) { context.Logger.ResponseWithVaryStarNotCacheable(); return(false); } // Check private if (HeaderUtilities.ContainsCacheDirective(responseCacheControlHeader, CacheControlHeaderValue.PrivateString)) { context.Logger.ResponseWithPrivateNotCacheable(); return(false); } // Check response code if (response.StatusCode != StatusCodes.Status200OK) { context.Logger.ResponseWithUnsuccessfulStatusCodeNotCacheable(response.StatusCode); return(false); } // Check response freshness if (!context.ResponseDate.HasValue) { if (!context.ResponseSharedMaxAge.HasValue && !context.ResponseMaxAge.HasValue && context.ResponseTime !.Value >= context.ResponseExpires) { context.Logger.ExpirationExpiresExceeded(context.ResponseTime.Value, context.ResponseExpires.Value); return(false); } } else { var age = context.ResponseTime !.Value - context.ResponseDate.Value; // Validate shared max age if (age >= context.ResponseSharedMaxAge) { context.Logger.ExpirationSharedMaxAgeExceeded(age, context.ResponseSharedMaxAge.Value); return(false); } else if (!context.ResponseSharedMaxAge.HasValue) { // Validate max age if (age >= context.ResponseMaxAge) { context.Logger.ExpirationMaxAgeExceeded(age, context.ResponseMaxAge.Value); return(false); } else if (!context.ResponseMaxAge.HasValue) { // Validate expiration if (context.ResponseTime.Value >= context.ResponseExpires) { context.Logger.ExpirationExpiresExceeded(context.ResponseTime.Value, context.ResponseExpires.Value); return(false); } } } } return(true); }
public virtual bool AllowCacheStorage(ResponseCachingContext context) { // Check request no-store return(!HeaderUtilities.ContainsCacheDirective(context.HttpContext.Request.Headers.CacheControl, CacheControlHeaderValue.NoStoreString)); }
public virtual bool IsCachedEntryFresh(ResponseCachingContext context) { var age = context.CachedEntryAge !.Value; var cachedCacheControlHeaders = context.CachedResponseHeaders.CacheControl; var requestCacheControlHeaders = context.HttpContext.Request.Headers.CacheControl; // Add min-fresh requirements if (HeaderUtilities.TryParseSeconds(requestCacheControlHeaders, CacheControlHeaderValue.MinFreshString, out var minFresh)) { age += minFresh.Value; context.Logger.ExpirationMinFreshAdded(minFresh.Value); } // Validate shared max age, this overrides any max age settings for shared caches TimeSpan?cachedSharedMaxAge; HeaderUtilities.TryParseSeconds(cachedCacheControlHeaders, CacheControlHeaderValue.SharedMaxAgeString, out cachedSharedMaxAge); if (age >= cachedSharedMaxAge) { // shared max age implies must revalidate context.Logger.ExpirationSharedMaxAgeExceeded(age, cachedSharedMaxAge.Value); return(false); } else if (!cachedSharedMaxAge.HasValue) { TimeSpan?requestMaxAge; HeaderUtilities.TryParseSeconds(requestCacheControlHeaders, CacheControlHeaderValue.MaxAgeString, out requestMaxAge); TimeSpan?cachedMaxAge; HeaderUtilities.TryParseSeconds(cachedCacheControlHeaders, CacheControlHeaderValue.MaxAgeString, out cachedMaxAge); var lowestMaxAge = cachedMaxAge < requestMaxAge ? cachedMaxAge : requestMaxAge ?? cachedMaxAge; // Validate max age if (age >= lowestMaxAge) { // Must revalidate or proxy revalidate if (HeaderUtilities.ContainsCacheDirective(cachedCacheControlHeaders, CacheControlHeaderValue.MustRevalidateString) || HeaderUtilities.ContainsCacheDirective(cachedCacheControlHeaders, CacheControlHeaderValue.ProxyRevalidateString)) { context.Logger.ExpirationMustRevalidate(age, lowestMaxAge.Value); return(false); } TimeSpan?requestMaxStale; var maxStaleExist = HeaderUtilities.ContainsCacheDirective(requestCacheControlHeaders, CacheControlHeaderValue.MaxStaleString); HeaderUtilities.TryParseSeconds(requestCacheControlHeaders, CacheControlHeaderValue.MaxStaleString, out requestMaxStale); // Request allows stale values with no age limit if (maxStaleExist && !requestMaxStale.HasValue) { context.Logger.ExpirationInfiniteMaxStaleSatisfied(age, lowestMaxAge.Value); return(true); } // Request allows stale values with age limit if (requestMaxStale.HasValue && age - lowestMaxAge < requestMaxStale) { context.Logger.ExpirationMaxStaleSatisfied(age, lowestMaxAge.Value, requestMaxStale.Value); return(true); } context.Logger.ExpirationMaxAgeExceeded(age, lowestMaxAge.Value); return(false); } else if (!cachedMaxAge.HasValue && !requestMaxAge.HasValue) { // Validate expiration DateTimeOffset expires; if (HeaderUtilities.TryParseDate(context.CachedResponseHeaders.Expires.ToString(), out expires) && context.ResponseTime !.Value >= expires) { context.Logger.ExpirationExpiresExceeded(context.ResponseTime.Value, expires); return(false); } } } return(true); }
static bool AllowCacheStorage(HttpContext context) { // cache-control: no-store ? return(!HeaderUtilities.ContainsCacheDirective(context.Request.Headers[HeaderNames.CacheControl], CacheControlHeaderValue.NoStoreString)); }
public void ContainsCacheDirective_MatchesExactValue(string headerValues, string targetValue, bool contains) { Assert.Equal(contains, HeaderUtilities.ContainsCacheDirective(new StringValues(headerValues), targetValue)); }