Ejemplo n.º 1
0
        private Task <HttpResponseMessage> HandleSendAndContinuationForPutPatch(CacheKey cacheKey, HttpRequestMessage request,
                                                                                System.Threading.CancellationToken cancellationToken)
        {
            return(base.SendAsync(request, cancellationToken)
                   .ContinueWith(
                       task =>
            {
                var serverResponse = task.Result;

                if (serverResponse.IsSuccessStatusCode)
                {
                    // ensure no NULL dates
                    if (serverResponse.Headers.Date == null)
                    {
                        serverResponse.Headers.Date = DateTimeOffset.UtcNow;
                    }

                    // should we clear?

                    if ((_enableClearRelatedResourceRepresentationsAfterPut && request.Method == HttpMethod.Put)
                        ||
                        (_enableClearRelatedResourceRepresentationsAfterPatch && request.Method.Method.ToLower() == "patch"))
                    {
                        // clear related resources
                        //
                        // - remove resource with cachekey.  This must be done, as there's no
                        // guarantee the new response is cacheable.
                        //
                        // - look for resources in cache that start with
                        // the cachekey + "?" for querystring.

                        _cacheStore.RemoveAsync(cacheKey);
                        _cacheStore.RemoveRangeAsync(cacheKey.PrimaryKey + "?");
                    }


                    // check the response: is this response allowed to be cached?
                    bool isCacheable = HttpResponseHelpers.CanBeCached(serverResponse);

                    if (isCacheable)
                    {
                        // add the response to cache
                        _cacheStore.SetAsync(cacheKey, new CacheEntry(serverResponse));
                    }

                    // what about vary by headers (=> key should take this into account)?
                }

                return serverResponse;
            }));
        }
Ejemplo n.º 2
0
        private Task <HttpResponseMessage> HandleSendAndContinuation(CacheKey cacheKey, HttpRequestMessage request,
                                                                     System.Threading.CancellationToken cancellationToken, bool mustRevalidate)
        {
            return(base.SendAsync(request, cancellationToken)
                   .ContinueWith(
                       task =>
            {
                var serverResponse = task.Result;

                // if we had to revalidate & got a 304 returned, that means
                // we can get the response message from cache.
                if (mustRevalidate && serverResponse.StatusCode == HttpStatusCode.NotModified)
                {
                    var cacheEntry = _cacheStore.GetAsync(cacheKey).Result;
                    var responseFromCacheEntry = cacheEntry.HttpResponse;
                    responseFromCacheEntry.RequestMessage = request;

                    return responseFromCacheEntry;
                }

                if (serverResponse.IsSuccessStatusCode)
                {
                    // ensure no NULL dates
                    if (serverResponse.Headers.Date == null)
                    {
                        serverResponse.Headers.Date = DateTimeOffset.UtcNow;
                    }

                    // check the response: is this response allowed to be cached?
                    bool isCacheable = HttpResponseHelpers.CanBeCached(serverResponse);

                    if (isCacheable)
                    {
                        // add the response to cache
                        _cacheStore.SetAsync(cacheKey, new CacheEntry(serverResponse));
                    }


                    // what about vary by headers (=> key should take this into account)?
                }

                return serverResponse;
            }));
        }
Ejemplo n.º 3
0
        private Task <HttpResponseMessage> HandleHttpGet(HttpRequestMessage request,
                                                         System.Threading.CancellationToken cancellationToken)
        {
            // get VaryByHeaders - order in the request shouldn't matter, so order them so the
            // rest of the logic doesn't result in different keys.


            string primaryCacheKey  = CacheKeyHelpers.CreatePrimaryCacheKey(request);// request.RequestUri.ToString();
            bool   responseIsCached = false;
            HttpResponseMessage      responseFromCache     = null;
            IEnumerable <CacheEntry> cacheEntriesFromCache = null;

            // first, before even looking at the cache:
            // The Cache-Control: no-cache HTTP/1.1 header field is also intended for use in requests made by the client.
            // It is a means for the browser to tell the server and any intermediate caches that it wants a
            // fresh version of the resource.

            if (request.Headers.CacheControl != null && request.Headers.CacheControl.NoCache)
            {
                // Don't get from cache.  Get from server.
                return(HandleSendAndContinuation(
                           CacheKeyHelpers.CreateCacheKey(primaryCacheKey), request, cancellationToken, false));
            }



            // available in cache?
            var cacheEntriesFromCacheAsTask = _cacheStore.GetAsync(primaryCacheKey);

            if (cacheEntriesFromCacheAsTask.Result != default(IEnumerable <CacheEntry>))
            {
                cacheEntriesFromCache = cacheEntriesFromCacheAsTask.Result;

                // TODO: for all of these, check the varyby headers (secondary key).
                // An item is a match if secondary & primary keys both match!
                responseFromCache = cacheEntriesFromCache.First().HttpResponse;
                responseIsCached  = true;
            }

            if (responseIsCached)
            {
                // set the accompanying request message
                responseFromCache.RequestMessage = request;

                // Check conditions that might require us to revalidate/check

                // we must assume "the worst": get from server.

                bool mustRevalidate = HttpResponseHelpers.MustRevalidate(responseFromCache);

                if (mustRevalidate)
                {
                    // we must revalidate - add headers to the request for validation.
                    //
                    // we add both ETag & IfModifiedSince for better interop with various
                    // server-side caching handlers.
                    //
                    if (responseFromCache.Headers.ETag != null)
                    {
                        request.Headers.Add(HttpHeaderConstants.IfNoneMatch,
                                            responseFromCache.Headers.ETag.ToString());
                    }

                    if (responseFromCache.Content.Headers.LastModified != null)
                    {
                        request.Headers.Add(HttpHeaderConstants.IfModifiedSince,
                                            responseFromCache.Content.Headers.LastModified.Value.ToString("r"));
                    }

                    return(HandleSendAndContinuation(
                               CacheKeyHelpers.CreateCacheKey(primaryCacheKey), request, cancellationToken, true));
                }
                else
                {
                    // response is allowed to be cached and there's
                    // no need to revalidate: return the cached response
                    return(Task.FromResult(responseFromCache));
                }
            }
            else
            {
                // response isn't cached.  Get it, and (possibly) add it to cache.
                return(HandleSendAndContinuation(
                           CacheKeyHelpers.CreateCacheKey(primaryCacheKey), request, cancellationToken, false));
            }
        }