예제 #1
0
 public CachingHandler(ICacheStore cacheStore)
 {
     _cacheStore = cacheStore;
     VaryHeaderStore = new InMemoryVaryHeaderStore();
     DefaultVaryHeaders = new string[]{"Accept"};
 }
예제 #2
0
        public CachingHandler(ICacheStore cacheStore)
        {
            _cacheStore = cacheStore;
            UseConditionalPut = true;
            VaryHeaderStore = new InMemoryVaryHeaderStore();
            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).

                    if (!response.StatusCode.IsIn(_cacheableStatuses))
                        return ResponseValidationResult.NotCacheable;

                    if (!response.IsSuccessStatusCode || response.Headers.CacheControl == null ||
                        response.Headers.CacheControl.NoStore || response.Headers.CacheControl.NoCache)
                        return ResponseValidationResult.NotCacheable;

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

                    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.Content.Headers.Expires != null &&
                        response.Content.Headers.Expires < DateTimeOffset.UtcNow)
                        return response.Headers.CacheControl.MustRevalidate ? 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.MustRevalidate ? 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.MustRevalidate ? 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.NoCache || 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 CachingHandler(ICacheStore cacheStore)
        {
            _cacheStore = cacheStore;
            UseConditionalPut = true;
            MustRevalidateByDefault = true;
            VaryHeaderStore = new InMemoryVaryHeaderStore();
            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;

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

                    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;
                    }
                };
        }