Exemplo n.º 1
0
        protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            HttpResponseMessage response = null;

            CacheEnabledRequestMessage cacheRequest = request as CacheEnabledRequestMessage;

            if (cacheRequest != null && cacheRequest.CacheOptions.UseFileCache)
            {
                Uri uri = request.RequestUri;

                using (var uriLock = new UriLock(uri, cancellationToken))
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    // check cache
                    Stream stream = null;
                    if (_fileCache.TryGet(uri, out stream))
                    {
                        DataTraceSources.Verbose("[HttpClient] Cached Length: {0}", "" + stream.Length);

                        response = new CacheResponse(stream);
                    }
                    else
                    {
                        // get the item and add it to the cache
                        DataTraceSources.Verbose("[HttpClient] GET {0}", uri.AbsoluteUri);

                        response = await base.SendAsync(request, cancellationToken);

                        if (response.IsSuccessStatusCode)
                        {
                            DataTraceSources.Verbose("[HttpClient] Caching {0}");
                            _fileCache.Add(uri, cacheRequest.CacheOptions.MaxCacheLife, await response.Content.ReadAsStreamAsync());
                        }
                    }
                }
            }

            if (response == null)
            {
                // skip cache
                DataTraceSources.Verbose("[HttpClient] GET {0}", request.RequestUri.AbsoluteUri);
                response = await base.SendAsync(request, cancellationToken);
            }

            return(response);
        }
Exemplo n.º 2
0
        private async Task <JObject> GetFileInternal(Uri uri, TimeSpan cacheTime, bool cacheInGraph = true, bool cloneJson = true)
        {
            if (uri == null)
            {
                throw new ArgumentNullException("uri");
            }

            if (cacheTime == null)
            {
                throw new ArgumentNullException("cacheTime");
            }

            bool cache = cacheTime.TotalSeconds > 0;

            // request the root document
            Uri fixedUri = Utility.GetUriWithoutHash(uri);

            Stream  stream       = null;
            JObject result       = null;
            JObject clonedResult = null; // the copy we give the caller

            try
            {
                using (var uriLock = new UriLock(fixedUri))
                {
                    if (!cache || !_fileCache.TryGet(fixedUri, out stream))
                    {
                        // the stream was not in the cache or we are skipping the cache
                        int tries = 0;

                        // try up to 5 times to be a little more robust
                        while (stream == null && tries < 5)
                        {
                            tries++;

                            try
                            {
                                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, fixedUri.AbsoluteUri);

                                DataTraceSources.Verbose("[HttpClient] GET {0}", fixedUri.AbsoluteUri);

                                var response = await _httpClient.SendAsync(request);

                                Debug.Assert(response.StatusCode == HttpStatusCode.OK, "Received non-OK status code response from " + request.RequestUri.ToString());
                                if (response.StatusCode == HttpStatusCode.OK)
                                {
                                    stream = await response.Content.ReadAsStreamAsync();

                                    if (stream != null)
                                    {
                                        if (cache)
                                        {
                                            DataTraceSources.Verbose("[HttpClient] Caching {0}");
                                            _fileCache.Add(fixedUri, _lifeSpan, stream);
                                        }

                                        DataTraceSources.Verbose("[HttpClient] 200 OK Length: {0}", "" + stream.Length);
                                        result = await StreamToJson(stream);
                                    }
                                }
                                else
                                {
                                    DataTraceSources.Verbose("[HttpClient] FAILED {0}", "" + (int)response.StatusCode);
                                    result = new JObject();
                                    result.Add("HttpStatusCode", (int)response.StatusCode);
                                }
                            }
                            catch (HttpRequestException ex)
                            {
                                Debug.Fail("WebRequest failed: " + ex.ToString());
                                DataTraceSources.Verbose("[HttpClient] FAILED {0}", ex.ToString());

                                // request error
                                result = new JObject();
                                result.Add("HttpRequestException", ex.ToString());
                            }
                        }
                    }
                    else
                    {
                        // the stream was in the cache
                        DataTraceSources.Verbose("[HttpClient] Cached Length: {0}", "" + stream.Length);
                        result = await StreamToJson(stream);
                    }
                }
            }
            finally
            {
                if (stream != null)
                {
                    stream.Dispose();
                }
            }

            if (result != null)
            {
                // this must be called before the entity cache thread starts using it
                if (cloneJson)
                {
                    clonedResult = result.DeepClone() as JObject;
                }
                else
                {
                    // in some scenarios we can skip cloning, such as when we are throwing away the result
                    clonedResult = result;
                }

                if (cacheInGraph)
                {
                    // this call is only blocking if the cache is overloaded
                    _entityCache.Add(result, fixedUri);
                }
            }

            return(clonedResult);
        }