Пример #1
0
        public CachingHandler(ICacheStore cacheStore, IVaryHeaderStore varyHeaderStore)
        {
            _cacheStore = cacheStore;
            UseConditionalPutPatchDelete = true;
            MustRevalidateByDefault      = true;
            VaryHeaderStore    = varyHeaderStore;
            DefaultVaryHeaders = new string[] { "Accept" };
            ResponseValidator  = (response) =>
            {
                // 13.4
                //Unless specifically constrained by a cache-control (section 14.9) directive, a caching system MAY always store
                // a successful response (see section 13.8) as a cache entry, MAY return it without validation if it
                // is fresh, and MAY return it after successful validation. If there is neither a cache validator nor an
                // explicit expiration time associated with a response, we do not expect it to be cached, but certain caches MAY violate this expectation
                // (for example, when little or no network connectivity is available).

                // 14.9.1
                // If the no-cache directive does not specify a field-name, then a cache MUST NOT use the response to satisfy a subsequent request without
                // successful revalidation with the origin server. This allows an origin server to prevent caching
                // even by caches that have been configured to return stale responses to client requests.
                //If the no-cache directive does specify one or more field-names, then a cache MAY use the response
                // to satisfy a subsequent request, subject to any other restrictions on caching. However, the specified
                // field-name(s) MUST NOT be sent in the response to a subsequent request without successful revalidation
                // with the origin server. This allows an origin server to prevent the re-use of certain header fields in a response, while still allowing caching of the rest of the response.
                if (!response.StatusCode.IsIn(_cacheableStatuses))
                {
                    return(ResponseValidationResult.NotCacheable);
                }

                if (!response.IsSuccessStatusCode || response.Headers.CacheControl == null ||
                    response.Headers.CacheControl.NoStore) //  || response.Headers.CacheControl.NoCache was removed. See issue
                {
                    return(ResponseValidationResult.NotCacheable);
                }

                if (response.Headers.Date == null)
                {
                    TraceWriter.WriteLine("Response date is NULL", TraceLevel.Warning);
                }

                response.Headers.Date = response.Headers.Date ?? DateTimeOffset.UtcNow; // this also helps in cache creation
                var dateTimeOffset = response.Headers.Date;

                TraceWriter.WriteLine(
                    String.Format("CachedResponse date was => {0} - compared to UTC.Now => {1}", dateTimeOffset, DateTimeOffset.UtcNow), TraceLevel.Verbose);

                if (response.Content == null)
                {
                    return(ResponseValidationResult.NotCacheable);
                }

                if (response.Headers.CacheControl.MaxAge == null &&
                    response.Headers.CacheControl.SharedMaxAge == null &&
                    response.Content.Headers.Expires == null)
                {
                    return(ResponseValidationResult.NotCacheable);
                }

                if (response.Headers.CacheControl.NoCache)
                {
                    return(ResponseValidationResult.MustRevalidate);
                }

                // here we use
                if (response.Content.Headers.Expires != null &&
                    response.Content.Headers.Expires < DateTimeOffset.UtcNow)
                {
                    return(response.Headers.CacheControl.ShouldRevalidate(MustRevalidateByDefault)
                        ? ResponseValidationResult.MustRevalidate : ResponseValidationResult.Stale);
                }

                if (response.Headers.CacheControl.MaxAge != null &&
                    DateTimeOffset.UtcNow > response.Headers.Date.Value.Add(response.Headers.CacheControl.MaxAge.Value))
                {
                    return(response.Headers.CacheControl.ShouldRevalidate(MustRevalidateByDefault)
                        ? ResponseValidationResult.MustRevalidate : ResponseValidationResult.Stale);
                }

                if (response.Headers.CacheControl.SharedMaxAge != null &&
                    DateTimeOffset.UtcNow > response.Headers.Date.Value.Add(response.Headers.CacheControl.SharedMaxAge.Value))
                {
                    return(response.Headers.CacheControl.ShouldRevalidate(MustRevalidateByDefault)
                        ? ResponseValidationResult.MustRevalidate : ResponseValidationResult.Stale);
                }

                return(ResponseValidationResult.OK);
            };

            _ignoreRequestRules = (request) =>
            {
                if (request.Method.IsCacheIgnorable())
                {
                    return(true);
                }

                // client can tell CachingHandler not to do caching for a particular request
                if (request.Headers.CacheControl != null)
                {
                    if (request.Headers.CacheControl.NoStore)
                    {
                        return(true);
                    }
                }

                return(false);
            };

            ResponseStoragePreparationRules = (response) =>
            {
                // 14.9.3
                // If a response includes both an Expires header and a max-age directive,
                // the max-age directive overrides the Expires header, even if the Expires header is more restrictive.
                if (response.Content.Headers.Expires != null &&
                    (response.Headers.CacheControl.MaxAge != null || response.Headers.CacheControl.SharedMaxAge != null))
                {
                    response.Content.Headers.Expires = null;
                }
            };
        }
Пример #2
0
        public CachingHandler(ICacheStore cacheStore, IVaryHeaderStore varyHeaderStore)
        {
            _cacheStore = cacheStore;
            UseConditionalPut = true;
            MustRevalidateByDefault = true;
            VaryHeaderStore = varyHeaderStore;
            DefaultVaryHeaders = new string[] { "Accept" };
            ResponseValidator = (response) =>
            {
                // 13.4
                //Unless specifically constrained by a cache-control (section 14.9) directive, a caching system MAY always store 
                // a successful response (see section 13.8) as a cache entry, MAY return it without validation if it 
                // is fresh, and MAY return it after successful validation. If there is neither a cache validator nor an 
                // explicit expiration time associated with a response, we do not expect it to be cached, but certain caches MAY violate this expectation 
                // (for example, when little or no network connectivity is available).

                // 14.9.1
                // If the no-cache directive does not specify a field-name, then a cache MUST NOT use the response to satisfy a subsequent request without 
                // successful revalidation with the origin server. This allows an origin server to prevent caching 
                // even by caches that have been configured to return stale responses to client requests.
                //If the no-cache directive does specify one or more field-names, then a cache MAY use the response 
                // to satisfy a subsequent request, subject to any other restrictions on caching. However, the specified 
                // field-name(s) MUST NOT be sent in the response to a subsequent request without successful revalidation 
                // with the origin server. This allows an origin server to prevent the re-use of certain header fields in a response, while still allowing caching of the rest of the response.
                if (!response.StatusCode.IsIn(_cacheableStatuses))
                    return ResponseValidationResult.NotCacheable;

                if (!response.IsSuccessStatusCode || response.Headers.CacheControl == null ||
                    response.Headers.CacheControl.NoStore) //  || response.Headers.CacheControl.NoCache was removed. See issue
                    return ResponseValidationResult.NotCacheable;

                if (response.Headers.Date == null)
                    TraceWriter.WriteLine("Response date is NULL", TraceLevel.Warning);

                response.Headers.Date = response.Headers.Date ?? DateTimeOffset.UtcNow; // this also helps in cache creation
                var dateTimeOffset = response.Headers.Date;

                TraceWriter.WriteLine(
                    String.Format("CachedResponse date was => {0} - compared to UTC.Now => {1}", dateTimeOffset, DateTimeOffset.UtcNow), TraceLevel.Verbose);

                if (response.Content == null)
                    return ResponseValidationResult.NotCacheable;

                if (response.Headers.CacheControl.MaxAge == null &&
                    response.Headers.CacheControl.SharedMaxAge == null &&
                    response.Content.Headers.Expires == null)
                    return ResponseValidationResult.NotCacheable;

                if (response.Headers.CacheControl.NoCache)
                    return ResponseValidationResult.MustRevalidate;

                // here we use 
                if (response.Content.Headers.Expires != null &&
                    response.Content.Headers.Expires < DateTimeOffset.UtcNow)
                    return response.Headers.CacheControl.ShouldRevalidate(MustRevalidateByDefault)
                        ? ResponseValidationResult.MustRevalidate : ResponseValidationResult.Stale;

                if (response.Headers.CacheControl.MaxAge != null &&
                    DateTimeOffset.UtcNow > response.Headers.Date.Value.Add(response.Headers.CacheControl.MaxAge.Value))
                    return response.Headers.CacheControl.ShouldRevalidate(MustRevalidateByDefault)
                        ? ResponseValidationResult.MustRevalidate : ResponseValidationResult.Stale;

                if (response.Headers.CacheControl.SharedMaxAge != null &&
                    DateTimeOffset.UtcNow > response.Headers.Date.Value.Add(response.Headers.CacheControl.SharedMaxAge.Value))
                    return response.Headers.CacheControl.ShouldRevalidate(MustRevalidateByDefault)
                        ? ResponseValidationResult.MustRevalidate : ResponseValidationResult.Stale;

                return ResponseValidationResult.OK;
            };

            _ignoreRequestRules = (request) =>
            {

                if (!request.Method.IsIn(HttpMethod.Get, HttpMethod.Put))
                    return true;

                // client can tell CachingHandler not to do caching for a particular request
                if (request.Headers.CacheControl != null)
                {
                    if (request.Headers.CacheControl.NoStore)
                        return true;
                }

                return false;
            };

            ResponseStoragePreparationRules = (response) =>
            {
                // 14.9.3
                // If a response includes both an Expires header and a max-age directive, 
                // the max-age directive overrides the Expires header, even if the Expires header is more restrictive.
                if (response.Content.Headers.Expires != null &&
                    (response.Headers.CacheControl.MaxAge != null || response.Headers.CacheControl.SharedMaxAge != null))
                {
                    response.Content.Headers.Expires = null;
                }
            };
            
        }
Пример #3
0
 public EsiFragmentCacheFacade(IEsiFragmentCache cache, IVaryHeaderStore varyHeaderStore)
 {
     _cache           = cache ?? throw new ArgumentNullException(nameof(cache));
     _varyHeaderStore = varyHeaderStore ?? throw new ArgumentNullException(nameof(varyHeaderStore));
 }