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); }); }
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); }
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(); }
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; }
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); }
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); }
protected static void SetResponseHeaders(IStaticResponse staticResponse, IOwinResponse response, params string[] except) { SetResponseHeaders(staticResponse.StatusCode, staticResponse.ReasonPhrase, staticResponse.Headers, response, except); }
protected static Task SendFullResponse(IStaticResponse response, Stream responseStream, IOwinContext ctx) { SetResponseHeaders(response, ctx.Response); return SendStreamAsync(responseStream, ctx.Response.Body, ctx.CallCancelled); }
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); }
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); }
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; }
protected abstract Task SendAsyncInternal(IStaticResponse response, Stream responseStream, IOwinContext ctx);
private Task ProcessResponseStream(IStaticResponse response, Stream stream, IOwinContext ctx) { var sender = responseSenderFactory.CreateSenderFor(response, ctx); return sender.SendAsync(response, stream, ctx); }