예제 #1
0
        protected override Task SendAsyncInternal(IStaticResponse response, Stream responseStream, IOwinContext ctx)
        {
            long? length = response.Headers.ContentLength.Value;
            if (!length.HasValue || length.Value == 0)
            {
                return SendFullResponse(response, responseStream, ctx);
            }

            SetResponseHeaders(response, ctx.Response, Constants.Http.Headers.ContentLength);
            ctx.Response.Headers.ContentEncoding.Value = CompressionMethod;

            if (!IsBodyRequested(ctx.Request.Method))
                return Task.FromResult<object>(null);

            var compressedStream = WrapToCompressedStream(ctx.Response.Body);
            return SendStreamAsync(responseStream, compressedStream, ctx.CallCancelled)
                .ContinueWith(
                    task =>
                        {
                            task.Wait(ctx.CallCancelled);
                            return compressedStream.FlushAsync(ctx.CallCancelled);
                        }, TaskContinuationOptions.ExecuteSynchronously)
                .Unwrap()
                .ContinueWith(
                    task =>
                        {
                            compressedStream.Close();
                            task.Wait(ctx.CallCancelled);
                        });
        }
예제 #2
0
 public Task SendAsync(IStaticResponse response, Stream responseStream, IOwinContext context)
 {
     if (response.StatusCode != Constants.Http.StatusCodes.Successful.Ok)
     {
         return SendFullResponse(response, responseStream, context);
     }
     return ProcessCacheHeaders(response, responseStream, context) ?? SendAsyncInternal(response, responseStream, context);
 }
예제 #3
0
 public IResponseSender CreateSenderFor(IStaticResponse response, IOwinContext context)
 {
     if (!CanResponseBeCompressed(response))
         return new RangedResponseSender();
     string compressionMethod = GetClientCompressionMethod(context);
     if (compressionMethod == null)
         return new RangedResponseSender();
     if (string.CompareOrdinal(compressionMethod, "gzip") == 0)
         return new GZippedResponseSender();
     return new DeflatedResponseSender();
 }
예제 #4
0
 private bool CanResponseBeCompressed(IStaticResponse response)
 {
     if (!compressedContentFilter.IsActive() || response.StatusCode != Constants.Http.StatusCodes.Successful.Ok)
         return false;
     var propValues = response.Headers.ContentType.PropertyValues;
     if (propValues.Length == 0)
         return false;
     if (compressedContentFilter.Contains(propValues[0].Value))
     {
         return true;
     }
     return false;
 }
예제 #5
0
        protected override Task SendAsyncInternal(IStaticResponse response, Stream responseStream, IOwinContext ctx)
        {
            ctx.Response.Headers.AcceptRanges.AddAcceptValue(AllowedRange);
            var rangeHeader = ctx.Request.Headers.Range;
            if (!rangeHeader.Available)
            {
                return SendFullResponse(response, responseStream, ctx);
            }
            var range = rangeHeader.Range;
            if (!range.Valid)
            {
                return SendRequestedRangeNotSatisfiable(ctx, responseStream);
            }
            var ifRange = ctx.Request.Headers.IfRange;
            if (ifRange.Available && !IfRange(ifRange, response.Headers.ETag.Value, response.Headers.LastModified.Value))
            {
                return SendFullResponse(response, responseStream, ctx);
            }

            return SendRange(range, response, responseStream, ctx);
        }
예제 #6
0
        private static Task SendRange(HttpRange range, IStaticResponse response, Stream responseStream, IOwinContext ctx)
        {
            long? length = response.Headers.ContentLength.Value;
            if (!length.HasValue || length.Value == 0)
            {
                SendFullResponse(response, responseStream, ctx);
            }

            long start, end;
            // ReSharper disable PossibleInvalidOperationException
            long rangeLength = GetRangeLength(range, length.Value, out start, out end);
            // ReSharper restore PossibleInvalidOperationException
            if (start < 0 || start >= length.Value || end >= length.Value || rangeLength <= 0)
            {
                return SendRequestedRangeNotSatisfiable(ctx, responseStream);
            }

            SetResponseHeaders(Constants.Http.StatusCodes.Successful.PartialContent, response.Headers, ctx.Response,
                               Constants.Http.Headers.ContentLength);
            ctx.Response.Headers.ContentRange.Range = new HttpContentRange(start, end, length.Value);
            ctx.Response.Headers.ContentLength.Value = rangeLength;

            return SendStreamAsync(responseStream, ctx.Response.Body, start, rangeLength, ctx.CallCancelled);
        }
예제 #7
0
 protected static void SetResponseHeaders(IStaticResponse staticResponse, IOwinResponse response, params string[] except)
 {
     SetResponseHeaders(staticResponse.StatusCode, staticResponse.ReasonPhrase, staticResponse.Headers, response, except);
 }
예제 #8
0
 protected static Task SendFullResponse(IStaticResponse response, Stream responseStream, IOwinContext ctx)
 {
     SetResponseHeaders(response, ctx.Response);
     return SendStreamAsync(responseStream, ctx.Response.Body, ctx.CallCancelled);
 }
예제 #9
0
 private static Task SendPreconditionResult(PreconditionResult result, IStaticResponse response, Stream responseStream, IOwinContext ctx)
 {
     var cacheStatus = result == PreconditionResult.PreconditionFailed
                           ? Constants.Http.StatusCodes.ClientError.PreconditionFailed
                           : Constants.Http.StatusCodes.Redirection.NotModified;
     return SendCacheStatus(response, responseStream, ctx, cacheStatus);
 }
예제 #10
0
 private static Task SendCacheStatus(IStaticResponse response, Stream responseStream, IOwinContext ctx, int statusCode)
 {
     responseStream.Close();
     SetResponseHeaders(statusCode, response.Headers, ctx.Response, Constants.Http.Headers.ContentLength);
     return Task.FromResult<object>(null);
 }
예제 #11
0
        private static Task ProcessCacheHeaders(IStaticResponse response, Stream responseStream, IOwinContext ctx)
        {
            PreconditionResult preconditionResult;

            var respETag = response.Headers.ETag.Value;
            if (!string.IsNullOrEmpty(respETag))
            {
                preconditionResult = IfMatch(ctx, respETag);
                if (preconditionResult != PreconditionResult.Continue)
                {
                    return SendPreconditionResult(preconditionResult, response, responseStream, ctx);
                }
                preconditionResult = IfNoneMatch(ctx, respETag);
                if (preconditionResult != PreconditionResult.Continue)
                {
                    return SendPreconditionResult(preconditionResult, response, responseStream, ctx);
                }
            }

            var lastModified = response.Headers.LastModified.Value;
            if (lastModified.HasValue)
            {
                preconditionResult = IfModifiedSince(ctx, lastModified.Value);
                if (preconditionResult != PreconditionResult.Continue)
                {
                    return SendPreconditionResult(preconditionResult, response, responseStream, ctx);
                }
                preconditionResult = IfUnmodifiedSince(ctx, lastModified.Value);
                if (preconditionResult != PreconditionResult.Continue)
                {
                    return SendPreconditionResult(preconditionResult, response, responseStream, ctx);
                }
            }

            return null;
        }
예제 #12
0
 protected abstract Task SendAsyncInternal(IStaticResponse response, Stream responseStream, IOwinContext ctx);
예제 #13
0
 private Task ProcessResponseStream(IStaticResponse response, Stream stream, IOwinContext ctx)
 {
     var sender = responseSenderFactory.CreateSenderFor(response, ctx);
     return sender.SendAsync(response, stream, ctx);
 }