private Task <HttpResponseMessage> HandleHttpPutOrPatch(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { string primaryCacheKey = CacheKeyHelpers.CreatePrimaryCacheKey(request); var cacheKey = CacheKeyHelpers.CreateCacheKey(primaryCacheKey); // cached + conditional PUT or cached + conditional PATCH if ((_enableConditionalPut && request.Method == HttpMethod.Put) || (_enableConditionalPatch && request.Method.Method.ToLower() == "patch")) { bool addCachingHeaders = false; HttpResponseMessage responseFromCache = null; // available in cache? var responseFromCacheAsTask = _cacheStore.GetAsync(cacheKey); if (responseFromCacheAsTask.Result != null) { addCachingHeaders = true; responseFromCache = responseFromCacheAsTask.Result.HttpResponse; } if (addCachingHeaders) { // set etag / lastmodified. Both are set for better compatibility // with different backend caching systems. if (responseFromCache.Headers.ETag != null) { request.Headers.Add(HttpHeaderConstants.IfMatch, responseFromCache.Headers.ETag.ToString()); } if (responseFromCache.Content.Headers.LastModified != null) { request.Headers.Add(HttpHeaderConstants.IfUnmodifiedSince, responseFromCache.Content.Headers.LastModified.Value.ToString("r")); } } } return(HandleSendAndContinuationForPutPatch(cacheKey, request, cancellationToken)); }
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)); } }