Ejemplo n.º 1
0
        private async Task <IHasOptions> GetStaticResult(IRequest requestContext, StaticResultOptions options, bool compress)
        {
            var isHeadRequest   = options.IsHeadRequest;
            var factoryFn       = options.ContentFactory;
            var contentType     = options.ContentType;
            var responseHeaders = options.ResponseHeaders;

            var requestedCompressionType = requestContext.GetCompressionType();

            if (!compress || string.IsNullOrEmpty(requestedCompressionType))
            {
                var rangeHeader = requestContext.GetHeader("Range");

                var stream = await factoryFn().ConfigureAwait(false);

                if (!string.IsNullOrEmpty(rangeHeader))
                {
                    return(new RangeRequestWriter(rangeHeader, stream, contentType, isHeadRequest, _logger)
                    {
                        OnComplete = options.OnComplete
                    });
                }

                responseHeaders["Content-Length"] = stream.Length.ToString(UsCulture);

                if (isHeadRequest)
                {
                    stream.Dispose();

                    return(GetHttpResult(new byte[] { }, contentType));
                }

                return(new StreamWriter(stream, contentType, _logger)
                {
                    OnComplete = options.OnComplete,
                    OnError = options.OnError
                });
            }

            string content;

            using (var stream = await factoryFn().ConfigureAwait(false))
            {
                using (var reader = new StreamReader(stream))
                {
                    content = await reader.ReadToEndAsync().ConfigureAwait(false);
                }
            }

            var contents = content.Compress(requestedCompressionType);

            responseHeaders["Content-Length"] = contents.Length.ToString(UsCulture);

            if (isHeadRequest)
            {
                return(GetHttpResult(new byte[] { }, contentType));
            }

            return(new CompressedResult(contents, requestedCompressionType, contentType));
        }
Ejemplo n.º 2
0
        public async Task <object> GetStaticResult(IRequest requestContext, StaticResultOptions options)
        {
            var cacheKey = options.CacheKey;

            options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
            var contentType = options.ContentType;

            if (cacheKey == Guid.Empty)
            {
                throw new ArgumentNullException("cacheKey");
            }
            if (options.ContentFactory == null)
            {
                throw new ArgumentNullException("factoryFn");
            }

            var key = cacheKey.ToString("N");

            // See if the result is already cached in the browser
            var result = GetCachedResult(requestContext, options.ResponseHeaders, cacheKey, key, options.DateLastModified, options.CacheDuration, contentType);

            if (result != null)
            {
                return(result);
            }

            var compress   = ShouldCompressResponse(requestContext, contentType);
            var hasOptions = await GetStaticResult(requestContext, options, compress).ConfigureAwait(false);

            AddResponseHeaders(hasOptions, options.ResponseHeaders);

            return(hasOptions);
        }
Ejemplo n.º 3
0
        private async Task <IHasHeaders> GetStaticResult(IRequest requestContext, StaticResultOptions options, bool compress)
        {
            var isHeadRequest   = options.IsHeadRequest;
            var factoryFn       = options.ContentFactory;
            var contentType     = options.ContentType;
            var responseHeaders = options.ResponseHeaders;

            var requestedCompressionType = GetCompressionType(requestContext);

            if (!compress || string.IsNullOrEmpty(requestedCompressionType))
            {
                var rangeHeader = requestContext.Headers.Get("Range");

                if (!isHeadRequest && !string.IsNullOrWhiteSpace(options.Path))
                {
                    return(new FileWriter(options.Path, contentType, rangeHeader, _logger, _fileSystem)
                    {
                        OnComplete = options.OnComplete,
                        OnError = options.OnError,
                        FileShare = options.FileShare
                    });
                }

                if (!string.IsNullOrEmpty(rangeHeader))
                {
                    var stream = await factoryFn().ConfigureAwait(false);

                    return(new RangeRequestWriter(rangeHeader, stream, contentType, isHeadRequest, _logger)
                    {
                        OnComplete = options.OnComplete
                    });
                }
                else
                {
                    var stream = await factoryFn().ConfigureAwait(false);

                    responseHeaders["Content-Length"] = stream.Length.ToString(UsCulture);

                    if (isHeadRequest)
                    {
                        stream.Dispose();

                        return(GetHttpResult(new byte[] { }, contentType, true));
                    }

                    return(new StreamWriter(stream, contentType, _logger)
                    {
                        OnComplete = options.OnComplete,
                        OnError = options.OnError
                    });
                }
            }

            using (var stream = await factoryFn().ConfigureAwait(false))
            {
                return(await GetCompressedResult(stream, requestedCompressionType, responseHeaders, isHeadRequest, contentType).ConfigureAwait(false));
            }
        }
Ejemplo n.º 4
0
        public async Task <object> GetStaticResult(IRequest requestContext, StaticResultOptions options)
        {
            options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            var contentType = options.ContentType;

            if (!StringValues.IsNullOrEmpty(requestContext.Headers[HeaderNames.IfModifiedSince]))
            {
                // See if the result is already cached in the browser
                var result = GetCachedResult(requestContext, options.ResponseHeaders, options);

                if (result != null)
                {
                    return(result);
                }
            }

            // TODO: We don't really need the option value
            var isHeadRequest   = options.IsHeadRequest || string.Equals(requestContext.Verb, "HEAD", StringComparison.OrdinalIgnoreCase);
            var factoryFn       = options.ContentFactory;
            var responseHeaders = options.ResponseHeaders;

            AddCachingHeaders(responseHeaders, options.CacheDuration, false, options.DateLastModified);
            AddAgeHeader(responseHeaders, options.DateLastModified);

            var rangeHeader = requestContext.Headers[HeaderNames.Range];

            if (!isHeadRequest && !string.IsNullOrEmpty(options.Path))
            {
                var hasHeaders = new FileWriter(options.Path, contentType, rangeHeader, _logger, _fileSystem, _streamHelper)
                {
                    OnComplete = options.OnComplete,
                    OnError    = options.OnError,
                    FileShare  = options.FileShare
                };

                AddResponseHeaders(hasHeaders, options.ResponseHeaders);
                return(hasHeaders);
            }

            var stream = await factoryFn().ConfigureAwait(false);

            var totalContentLength = options.ContentLength;

            if (!totalContentLength.HasValue)
            {
                try
                {
                    totalContentLength = stream.Length;
                }
                catch (NotSupportedException)
                {
                }
            }

            if (!string.IsNullOrWhiteSpace(rangeHeader) && totalContentLength.HasValue)
            {
                var hasHeaders = new RangeRequestWriter(rangeHeader, totalContentLength.Value, stream, contentType, isHeadRequest, _logger)
                {
                    OnComplete = options.OnComplete
                };

                AddResponseHeaders(hasHeaders, options.ResponseHeaders);
                return(hasHeaders);
            }
            else
            {
                if (totalContentLength.HasValue)
                {
                    responseHeaders["Content-Length"] = totalContentLength.Value.ToString(CultureInfo.InvariantCulture);
                }

                if (isHeadRequest)
                {
                    using (stream)
                    {
                        return(GetHttpResult(requestContext, Array.Empty <byte>(), contentType, true, responseHeaders));
                    }
                }

                var hasHeaders = new StreamWriter(stream, contentType)
                {
                    OnComplete = options.OnComplete,
                    OnError    = options.OnError
                };

                AddResponseHeaders(hasHeaders, options.ResponseHeaders);
                return(hasHeaders);
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Pres the process optimized result.
        /// </summary>
        private object GetCachedResult(IRequest requestContext, IDictionary <string, string> responseHeaders, StaticResultOptions options)
        {
            bool noCache = (requestContext.Headers[HeaderNames.CacheControl].ToString()).IndexOf("no-cache", StringComparison.OrdinalIgnoreCase) != -1;

            AddCachingHeaders(responseHeaders, options.CacheDuration, noCache, options.DateLastModified);

            if (!noCache)
            {
                DateTime.TryParse(requestContext.Headers[HeaderNames.IfModifiedSince], out var ifModifiedSinceHeader);

                if (IsNotModified(ifModifiedSinceHeader, options.CacheDuration, options.DateLastModified))
                {
                    AddAgeHeader(responseHeaders, options.DateLastModified);

                    var result = new HttpResult(Array.Empty <byte>(), options.ContentType ?? "text/html", HttpStatusCode.NotModified);

                    AddResponseHeaders(result, responseHeaders);

                    return(result);
                }
            }

            return(null);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Pres the process optimized result.
        /// </summary>
        private object GetCachedResult(IRequest requestContext, IDictionary <string, string> responseHeaders, StaticResultOptions options)
        {
            bool noCache = (requestContext.Headers[HeaderNames.CacheControl].ToString()).IndexOf("no-cache", StringComparison.OrdinalIgnoreCase) != -1;

            AddCachingHeaders(responseHeaders, options.CacheDuration, noCache, options.DateLastModified);

            if (!noCache)
            {
                if (!DateTime.TryParseExact(requestContext.Headers[HeaderNames.IfModifiedSince], HttpDateFormat, _enUSculture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var ifModifiedSinceHeader))
                {
                    _logger.LogDebug("Failed to parse If-Modified-Since header date: {0}", requestContext.Headers[HeaderNames.IfModifiedSince]);
                    return(null);
                }

                if (IsNotModified(ifModifiedSinceHeader, options.CacheDuration, options.DateLastModified))
                {
                    AddAgeHeader(responseHeaders, options.DateLastModified);

                    var result = new HttpResult(Array.Empty <byte>(), options.ContentType ?? "text/html", HttpStatusCode.NotModified);

                    AddResponseHeaders(result, responseHeaders);

                    return(result);
                }
            }

            return(null);
        }
Ejemplo n.º 7
0
        public async Task <object> GetStaticResult(IRequest requestContext, StaticResultOptions options)
        {
            var cacheKey = options.CacheKey;

            options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
            var contentType = options.ContentType;

            if (cacheKey == Guid.Empty)
            {
                throw new ArgumentNullException("cacheKey");
            }

            var key = cacheKey.ToString("N");

            // See if the result is already cached in the browser
            var result = GetCachedResult(requestContext, options.ResponseHeaders, cacheKey, key, options.DateLastModified, options.CacheDuration, contentType);

            if (result != null)
            {
                return(result);
            }

            // TODO: We don't really need the option value
            var isHeadRequest   = options.IsHeadRequest || string.Equals(requestContext.Verb, "HEAD", StringComparison.OrdinalIgnoreCase);
            var factoryFn       = options.ContentFactory;
            var responseHeaders = options.ResponseHeaders;

            //var requestedCompressionType = GetCompressionType(requestContext);

            var rangeHeader = requestContext.Headers.Get("Range");

            if (!isHeadRequest && !string.IsNullOrEmpty(options.Path))
            {
                var hasHeaders = new FileWriter(options.Path, contentType, rangeHeader, _logger, _fileSystem)
                {
                    OnComplete = options.OnComplete,
                    OnError    = options.OnError,
                    FileShare  = options.FileShare
                };

                AddResponseHeaders(hasHeaders, options.ResponseHeaders);
                return(hasHeaders);
            }

            if (!string.IsNullOrWhiteSpace(rangeHeader))
            {
                var stream = await factoryFn().ConfigureAwait(false);

                var hasHeaders = new RangeRequestWriter(rangeHeader, stream, contentType, isHeadRequest, _logger)
                {
                    OnComplete = options.OnComplete
                };

                AddResponseHeaders(hasHeaders, options.ResponseHeaders);
                return(hasHeaders);
            }
            else
            {
                var stream = await factoryFn().ConfigureAwait(false);

                responseHeaders["Content-Length"] = stream.Length.ToString(UsCulture);

                if (isHeadRequest)
                {
                    stream.Dispose();

                    return(GetHttpResult(requestContext, new byte[] { }, contentType, true, responseHeaders));
                }

                var hasHeaders = new StreamWriter(stream, contentType, _logger)
                {
                    OnComplete = options.OnComplete,
                    OnError    = options.OnError
                };

                AddResponseHeaders(hasHeaders, options.ResponseHeaders);
                return(hasHeaders);
            }
        }
Ejemplo n.º 8
0
        public async Task <object> GetStaticResult(IRequest requestContext, StaticResultOptions options)
        {
            options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            var contentType = options.ContentType;
            var etag        = requestContext.Headers.Get("If-None-Match");
            var cacheKey    = etag != null ? new Guid(etag.Trim('\"')) : Guid.Empty;

            if (!cacheKey.Equals(Guid.Empty))
            {
                var key = cacheKey.ToString("N");

                // See if the result is already cached in the browser
                var result = GetCachedResult(requestContext, options.ResponseHeaders, cacheKey, key, options.DateLastModified, options.CacheDuration, contentType);

                if (result != null)
                {
                    return(result);
                }
            }

            // TODO: We don't really need the option value
            var isHeadRequest   = options.IsHeadRequest || string.Equals(requestContext.Verb, "HEAD", StringComparison.OrdinalIgnoreCase);
            var factoryFn       = options.ContentFactory;
            var responseHeaders = options.ResponseHeaders;

            var rangeHeader = requestContext.Headers.Get("Range");

            if (!isHeadRequest && !string.IsNullOrEmpty(options.Path))
            {
                var hasHeaders = new FileWriter(options.Path, contentType, rangeHeader, _logger, _fileSystem)
                {
                    OnComplete = options.OnComplete,
                    OnError    = options.OnError,
                    FileShare  = options.FileShare
                };

                AddResponseHeaders(hasHeaders, options.ResponseHeaders);
                // Generate an ETag based on identifying information - TODO read contents from filesystem instead?
                var responseId = $"{hasHeaders.ContentType}{options.Path}{hasHeaders.TotalContentLength}";
                var hashedId   = MD5.Create().ComputeHash(Encoding.Default.GetBytes(responseId));
                hasHeaders.Headers["ETag"] = new Guid(hashedId).ToString("N");

                return(hasHeaders);
            }

            var stream = await factoryFn().ConfigureAwait(false);

            // Generate an etag based on stream content
            var streamHash = MD5.Create().ComputeHash(stream);
            var newEtag    = new Guid(streamHash).ToString("N");

            // reset position so the response can re-use it -- TODO is this ok?
            stream.Position = 0;

            var totalContentLength = options.ContentLength;

            if (!totalContentLength.HasValue)
            {
                try
                {
                    totalContentLength = stream.Length;
                }
                catch (NotSupportedException)
                {
                }
            }

            if (!string.IsNullOrWhiteSpace(rangeHeader) && totalContentLength.HasValue)
            {
                var hasHeaders = new RangeRequestWriter(rangeHeader, totalContentLength.Value, stream, contentType, isHeadRequest, _logger)
                {
                    OnComplete = options.OnComplete
                };

                AddResponseHeaders(hasHeaders, options.ResponseHeaders);
                hasHeaders.Headers["ETag"] = newEtag;
                return(hasHeaders);
            }
            else
            {
                if (totalContentLength.HasValue)
                {
                    responseHeaders["Content-Length"] = totalContentLength.Value.ToString(UsCulture);
                }

                if (isHeadRequest)
                {
                    using (stream)
                    {
                        return(GetHttpResult(requestContext, Array.Empty <byte>(), contentType, true, responseHeaders));
                    }
                }

                var hasHeaders = new StreamWriter(stream, contentType, _logger)
                {
                    OnComplete = options.OnComplete,
                    OnError    = options.OnError
                };

                AddResponseHeaders(hasHeaders, options.ResponseHeaders);
                hasHeaders.Headers["ETag"] = newEtag;
                return(hasHeaders);
            }
        }