public static bool TryParse(string timedETagValue, out TimedEntityTagHeaderValue value)
        {
            value = null;
            if (timedETagValue == null)
            {
                return false;
            }

            string[] strings = timedETagValue.Split(new[] { "\r\n" }, StringSplitOptions.None);
            if (strings.Length != 2)
            {
                return false;
            }

            EntityTagHeaderValue etag;
            DateTimeOffset lastModified;
            if (!TryParse(strings[0], out etag))
            {
                return false;
            }

            if (!DateTimeOffset.TryParse(strings[1], out lastModified))
            {
                return false;
            }

            value = new TimedEntityTagHeaderValue(etag.Tag, etag.IsWeak)
            {
                LastModified = lastModified
            };
            return true;
        }
        public static bool TryParse(string timedETagValue, out TimedEntityTagHeaderValue value)
        {
            value = null;
            if (timedETagValue == null)
            {
                return(false);
            }

            string[] strings = timedETagValue.Split(new[] { "\r\n" }, StringSplitOptions.None);
            if (strings.Length != 2)
            {
                return(false);
            }

            EntityTagHeaderValue etag;
            DateTimeOffset       lastModified;

            if (!TryParse(strings[0], out etag))
            {
                return(false);
            }

            if (!DateTimeOffset.TryParse(strings[1], out lastModified))
            {
                return(false);
            }

            value = new TimedEntityTagHeaderValue(etag.Tag, etag.IsWeak)
            {
                LastModified = lastModified
            };
            return(true);
        }
 public void AddOrUpdate(EntityTagKey key, TimedEntityTagHeaderValue eTag)
 {
     _eTagCache.AddOrUpdate(key, eTag, (theKey, oldValue) => eTag);
     _routePatternCache.AddOrUpdate(key.RoutePattern, new HashSet<EntityTagKey> { key },
         (routePattern, hashSet) =>
         {
             hashSet.Add(key);
             return hashSet;
         });
 }
Exemple #4
0
 public void AddOrUpdate(EntityTagKey key, TimedEntityTagHeaderValue eTag)
 {
     _eTagCache.AddOrUpdate(key, eTag, (theKey, oldValue) => eTag);
     _routePatternCache.AddOrUpdate(key.RoutePattern, new HashSet <EntityTagKey> {
         key
     },
                                    (routePattern, hashSet) =>
     {
         hashSet.Add(key);
         return(hashSet);
     });
 }
Exemple #5
0
        /// <summary>
        /// Adds caching for GET and PUT if
        /// cache control provided is not null
        /// With PUT, since cache has been alreay invalidated,
        /// we provide the new ETag (old one has been cleared in invalidation phase)
        /// </summary>
        /// <param name="entityTagKey"></param>
        /// <param name="request"></param>
        /// <param name="response"></param>
        /// <param name="varyHeaders"></param>
        /// <returns></returns>
        internal Action AddCaching(
            EntityTagKey entityTagKey,
            HttpRequestMessage request,
            HttpResponseMessage response,
            IEnumerable <KeyValuePair <string, IEnumerable <string> > > varyHeaders)
        {
            return
                (() =>
            {
                CacheControlHeaderValue cacheControlHeaderValue = CacheControlHeaderProvider(request);
                if (cacheControlHeaderValue == null)
                {
                    return;
                }

                TimedEntityTagHeaderValue eTagValue;

                string uri = UriTrimmer(request.RequestUri);

                // in case of GET and no ETag
                // in case of PUT, we should return the new ETag of the resource
                // NOTE: No need to check if it is in the cache. If it were, it would not get
                // here
                if (request.Method == HttpMethod.Get || request.Method == HttpMethod.Put)
                {
                    // create new ETag only if it does not already exist
                    if (!_entityTagStore.TryGetValue(entityTagKey, out eTagValue))
                    {
                        eTagValue = new TimedEntityTagHeaderValue(ETagValueGenerator(uri, varyHeaders));
                        _entityTagStore.AddOrUpdate(entityTagKey, eTagValue);
                    }

                    // set ETag
                    response.Headers.ETag = eTagValue.ToEntityTagHeaderValue();

                    // set last-modified
                    if (AddLastModifiedHeader && response.Content != null &&
                        !response.Content.Headers.Any(x => x.Key.Equals(HttpHeaderNames.LastModified,
                                                                        StringComparison.CurrentCultureIgnoreCase)))
                    {
                        response.Content.Headers.Add(HttpHeaderNames.LastModified, eTagValue.LastModified.ToString("r"));
                    }

                    // set Vary
                    if (AddVaryHeader && _varyByHeaders != null && _varyByHeaders.Length > 0)
                    {
                        response.Headers.Add(HttpHeaderNames.Vary, _varyByHeaders);
                    }

                    response.Headers.TryAddWithoutValidation(HttpHeaderNames.CacheControl, cacheControlHeaderValue.ToString());
                }
            });
        }
Exemple #6
0
        internal Func <HttpRequestMessage, Task <HttpResponseMessage> > GetIfMatchNoneMatch()
        {
            return((request) =>
            {
                if (request.Method != HttpMethod.Get)
                {
                    return null;
                }

                ICollection <EntityTagHeaderValue> noneMatchTags = request.Headers.IfNoneMatch;
                ICollection <EntityTagHeaderValue> matchTags = request.Headers.IfMatch;

                if (matchTags.Count == 0 && noneMatchTags.Count == 0)
                {
                    return null; // no etag
                }

                if (matchTags.Count > 0 && noneMatchTags.Count > 0) // both if-match and if-none-match exist
                {
                    return new HttpResponseMessage(HttpStatusCode.BadRequest).ToTask();
                }

                bool isNoneMatch = noneMatchTags.Count > 0;
                ICollection <EntityTagHeaderValue> etags = isNoneMatch ? noneMatchTags : matchTags;

                string resource = UriTrimmer(request.RequestUri);
                IEnumerable <KeyValuePair <string, IEnumerable <string> > > headers =
                    request.Headers.Where(h => _varyByHeaders.Any(v => v.Equals(h.Key, StringComparison.CurrentCultureIgnoreCase)));
                EntityTagKey entityTagKey = EntityTagKeyGenerator(resource, headers);
                // compare the Etag with the one in the cache
                // do conditional get.
                TimedEntityTagHeaderValue actualEtag = null;

                bool matchFound = false;
                if (_entityTagStore.TryGetValue(entityTagKey, out actualEtag))
                {
                    if (etags.Any(etag => etag.Tag == actualEtag.Tag))
                    {
                        matchFound = true;
                    }
                }
                return matchFound ^ isNoneMatch ? null : new NotModifiedResponse(actualEtag.ToEntityTagHeaderValue()).ToTask();
            });
        }
Exemple #7
0
 public bool TryGetValue(EntityTagKey key, out TimedEntityTagHeaderValue eTag)
 {
     return(_eTagCache.TryGetValue(key, out eTag));
 }
 public bool TryGetValue(EntityTagKey key, out TimedEntityTagHeaderValue eTag)
 {
     return _eTagCache.TryGetValue(key, out eTag);
 }
Exemple #9
0
        /// <summary>
        /// Adds caching for GET and PUT if 
        /// cache control provided is not null
        /// With PUT, since cache has been alreay invalidated,
        /// we provide the new ETag (old one has been cleared in invalidation phase)
        /// </summary>
        /// <param name="entityTagKey"></param>
        /// <param name="request"></param>
        /// <param name="response"></param>
        /// <param name="varyHeaders"></param>
        /// <returns></returns>
        internal Action AddCaching(
            EntityTagKey entityTagKey,
            HttpRequestMessage request,
            HttpResponseMessage response,
            IEnumerable<KeyValuePair<string, IEnumerable<string>>> varyHeaders)
        {
            return
                () =>
                {
                    CacheControlHeaderValue cacheControlHeaderValue = CacheControlHeaderProvider(request);
                    if (cacheControlHeaderValue == null)
                    {
                        return;
                    }

                    TimedEntityTagHeaderValue eTagValue;

                    string uri = UriTrimmer(request.RequestUri);

                    // in case of GET and no ETag
                    // in case of PUT, we should return the new ETag of the resource
                    // NOTE: No need to check if it is in the cache. If it were, it would not get
                    // here
                    if (request.Method == HttpMethod.Get || request.Method == HttpMethod.Put)
                    {
                        // create new ETag only if it does not already exist
                        if (!_entityTagStore.TryGetValue(entityTagKey, out eTagValue))
                        {
                            eTagValue = new TimedEntityTagHeaderValue(ETagValueGenerator(uri, varyHeaders));
                            _entityTagStore.AddOrUpdate(entityTagKey, eTagValue);
                        }

                        // set ETag
                        response.Headers.ETag = eTagValue.ToEntityTagHeaderValue();

                        // set last-modified
                        if (AddLastModifiedHeader && response.Content != null
                            && !response.Content.Headers.Any(x => x.Key.Equals(HttpHeaderNames.LastModified,
                                StringComparison.CurrentCultureIgnoreCase)))
                        {
                            response.Content.Headers.Add(HttpHeaderNames.LastModified, eTagValue.LastModified.ToString("r"));
                        }

                        // set Vary
                        if (AddVaryHeader && _varyByHeaders != null && _varyByHeaders.Length > 0)
                        {
                            response.Headers.Add(HttpHeaderNames.Vary, _varyByHeaders);
                        }

                        response.Headers.TryAddWithoutValidation(HttpHeaderNames.CacheControl, cacheControlHeaderValue.ToString());
                    }
                };
        }