Exemplo n.º 1
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);
            }
        }
Exemplo n.º 2
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);
            }
        }
Exemplo n.º 3
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);
            }
        }