Пример #1
0
        /// <summary>
        /// Caching Get request.
        /// </summary>
        public async Task <T> GetAsync <T>(
            HttpSourceCachedRequest request,
            Func <HttpSourceResult, Task <T> > processAsync,
            ILogger log,
            CancellationToken token)
        {
            var cacheResult = HttpCacheUtility.InitializeHttpCacheResult(
                HttpCacheDirectory,
                _sourceUri,
                request.CacheKey,
                request.CacheContext);

            return(await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                       cacheResult.CacheFile,
                       action : async lockedToken =>
            {
                cacheResult.Stream = TryReadCacheFile(request.Uri, cacheResult.MaxAge, cacheResult.CacheFile);

                if (cacheResult.Stream != null)
                {
                    log.LogInformation(string.Format(CultureInfo.InvariantCulture, "  " + Strings.Http_RequestLog, "CACHE", request.Uri));

                    // Validate the content fetched from the cache.
                    try
                    {
                        request.EnsureValidContents?.Invoke(cacheResult.Stream);

                        cacheResult.Stream.Seek(0, SeekOrigin.Begin);

                        var httpSourceResult = new HttpSourceResult(
                            HttpSourceResultStatus.OpenedFromDisk,
                            cacheResult.CacheFile,
                            cacheResult.Stream);

                        return await processAsync(httpSourceResult);
                    }
                    catch (Exception e)
                    {
                        cacheResult.Stream.Dispose();
                        cacheResult.Stream = null;

                        string message = string.Format(CultureInfo.CurrentCulture, Strings.Log_InvalidCacheEntry, request.Uri)
                                         + Environment.NewLine
                                         + ExceptionUtilities.DisplayMessage(e);
                        log.LogWarning(message);
                    }
                }

                Func <HttpRequestMessage> requestFactory = () =>
                {
                    var requestMessage = HttpRequestMessageFactory.Create(HttpMethod.Get, request.Uri, log);

                    foreach (var acceptHeaderValue in request.AcceptHeaderValues)
                    {
                        requestMessage.Headers.Accept.Add(acceptHeaderValue);
                    }

                    return requestMessage;
                };

                Func <Task <ThrottledResponse> > throttledResponseFactory = () => GetThrottledResponse(
                    requestFactory,
                    request.RequestTimeout,
                    request.DownloadTimeout,
                    request.MaxTries,
                    log,
                    lockedToken);

                using (var throttledResponse = await throttledResponseFactory())
                {
                    if (request.IgnoreNotFounds && throttledResponse.Response.StatusCode == HttpStatusCode.NotFound)
                    {
                        var httpSourceResult = new HttpSourceResult(HttpSourceResultStatus.NotFound);

                        return await processAsync(httpSourceResult);
                    }

                    if (throttledResponse.Response.StatusCode == HttpStatusCode.NoContent)
                    {
                        // Ignore reading and caching the empty stream.
                        var httpSourceResult = new HttpSourceResult(HttpSourceResultStatus.NoContent);

                        return await processAsync(httpSourceResult);
                    }

                    throttledResponse.Response.EnsureSuccessStatusCode();

                    if (!request.CacheContext.DirectDownload)
                    {
                        await HttpCacheUtility.CreateCacheFileAsync(
                            cacheResult,
                            throttledResponse.Response,
                            request.EnsureValidContents,
                            lockedToken);

                        using (var httpSourceResult = new HttpSourceResult(
                                   HttpSourceResultStatus.OpenedFromDisk,
                                   cacheResult.CacheFile,
                                   cacheResult.Stream))
                        {
                            return await processAsync(httpSourceResult);
                        }
                    }
                    else
                    {
                        // Note that we do not execute the content validator on the response stream when skipping
                        // the cache. We cannot seek on the network stream and it is not valuable to download the
                        // content twice just to validate the first time (considering that the second download could
                        // be different from the first thus rendering the first validation meaningless).
                        using (var stream = await throttledResponse.Response.Content.ReadAsStreamAsync())
                            using (var httpSourceResult = new HttpSourceResult(
                                       HttpSourceResultStatus.OpenedFromNetwork,
                                       cacheFileName: null,
                                       stream: stream))
                            {
                                return await processAsync(httpSourceResult);
                            }
                    }
                }
            },
                       token : token));
        }
Пример #2
0
        /// <summary>
        /// Caching Get request.
        /// </summary>
        public async Task <HttpSourceResult> GetAsync(
            HttpSourceCachedRequest request,
            ILogger log,
            CancellationToken token)
        {
            var result = HttpCacheUtility.InitializeHttpCacheResult(
                HttpCacheDirectory,
                _baseUri,
                request.CacheKey,
                request.CacheContext);

            return(await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                       result.CacheFile,
                       action : async lockedToken =>
            {
                result.Stream = TryReadCacheFile(request.Uri, result.MaxAge, result.CacheFile);

                if (result.Stream != null)
                {
                    log.LogInformation(string.Format(CultureInfo.InvariantCulture, "  " + Strings.Http_RequestLog, "CACHE", request.Uri));

                    // Validate the content fetched from the cache.
                    try
                    {
                        request.EnsureValidContents?.Invoke(result.Stream);

                        result.Stream.Seek(0, SeekOrigin.Begin);

                        return new HttpSourceResult(
                            HttpSourceResultStatus.OpenedFromDisk,
                            result.CacheFile,
                            result.Stream);
                    }
                    catch (Exception e)
                    {
                        result.Stream.Dispose();
                        result.Stream = null;

                        string message = string.Format(CultureInfo.CurrentCulture, Strings.Log_InvalidCacheEntry, request.Uri)
                                         + Environment.NewLine
                                         + ExceptionUtilities.DisplayMessage(e);
                        log.LogWarning(message);
                    }
                }

                Func <HttpRequestMessage> requestFactory = () =>
                {
                    var requestMessage = HttpRequestMessageFactory.Create(HttpMethod.Get, request.Uri, log);

                    foreach (var acceptHeaderValue in request.AcceptHeaderValues)
                    {
                        requestMessage.Headers.Accept.Add(acceptHeaderValue);
                    }

                    return requestMessage;
                };

                Func <Task <ThrottledResponse> > throttledResponseFactory = () => GetThrottledResponse(
                    requestFactory,
                    request.RequestTimeout,
                    request.DownloadTimeout,
                    log,
                    lockedToken);

                using (var throttledResponse = await throttledResponseFactory())
                {
                    if (request.IgnoreNotFounds && throttledResponse.Response.StatusCode == HttpStatusCode.NotFound)
                    {
                        return new HttpSourceResult(HttpSourceResultStatus.NotFound);
                    }

                    if (throttledResponse.Response.StatusCode == HttpStatusCode.NoContent)
                    {
                        // Ignore reading and caching the empty stream.
                        return new HttpSourceResult(HttpSourceResultStatus.NoContent);
                    }

                    throttledResponse.Response.EnsureSuccessStatusCode();

                    await HttpCacheUtility.CreateCacheFileAsync(
                        result,
                        request.Uri,
                        throttledResponse.Response,
                        request.CacheContext,
                        request.EnsureValidContents,
                        lockedToken);

                    return new HttpSourceResult(
                        HttpSourceResultStatus.OpenedFromDisk,
                        result.CacheFile,
                        result.Stream);
                }
            },
                       token : token));
        }