Skip to content
This repository has been archived by the owner on Nov 22, 2018. It is now read-only.

Commit

Permalink
#150 Handle OperationCancelledExceptions to prevent log noise
Browse files Browse the repository at this point in the history
  • Loading branch information
Tratcher committed Sep 6, 2016
1 parent df66f51 commit 83d7963
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 14 deletions.
10 changes: 10 additions & 0 deletions src/Microsoft.AspNetCore.StaticFiles/LoggerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ internal static class LoggerExtensions
private static Action<ILogger, StringValues, string, Exception> _logCopyingFileRange;
private static Action<ILogger, long, string, string, Exception> _logCopyingBytesToResponse;
private static Action<ILogger, string, Exception> _logMultipleFileRanges;
private static Action<ILogger, Exception> _logWriteCancelled;

static LoggerExtensions()
{
Expand Down Expand Up @@ -80,6 +81,10 @@ static LoggerExtensions()
logLevel: LogLevel.Warning,
eventId: 13,
formatString: "Multiple ranges are not allowed: '{Ranges}'");
_logWriteCancelled = LoggerMessage.Define(
logLevel: LogLevel.Debug,
eventId: 14,
formatString: "The file transmission was cancelled");
}

public static void LogRequestMethodNotSupported(this ILogger logger, string method)
Expand Down Expand Up @@ -155,5 +160,10 @@ public static void LogMultipleFileRanges(this ILogger logger, string range)
{
_logMultipleFileRanges(logger, range, null);
}

public static void LogWriteCancelled(this ILogger logger, Exception ex)
{
_logWriteCancelled(logger, ex);
}
}
}
40 changes: 26 additions & 14 deletions src/Microsoft.AspNetCore.StaticFiles/StaticFileContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
Expand Down Expand Up @@ -345,24 +346,29 @@ public Task SendStatusAsync(int statusCode)
public async Task SendAsync()
{
ApplyResponseHeaders(Constants.Status200Ok);

string physicalPath = _fileInfo.PhysicalPath;
var sendFile = _context.Features.Get<IHttpSendFileFeature>();
if (sendFile != null && !string.IsNullOrEmpty(physicalPath))
{
await sendFile.SendFileAsync(physicalPath, 0, _length, _context.RequestAborted);
// We don't need to directly cancel this, if the client disconnects it will fail silently.
await sendFile.SendFileAsync(physicalPath, 0, _length, CancellationToken.None);
return;
}

Stream readStream = _fileInfo.CreateReadStream();
try
{
// Larger StreamCopyBufferSize is required because in case of FileStream readStream isn't going to be buffering
await StreamCopyOperation.CopyToAsync(readStream, _response.Body, _length, StreamCopyBufferSize, _context.RequestAborted);
using (var readStream = _fileInfo.CreateReadStream())
{
// Larger StreamCopyBufferSize is required because in case of FileStream readStream isn't going to be buffering
await StreamCopyOperation.CopyToAsync(readStream, _response.Body, _length, StreamCopyBufferSize, _context.RequestAborted);
}
}
finally
catch (OperationCanceledException ex)
{
readStream.Dispose();
_logger.LogWriteCancelled(ex);
// Don't throw this exception, it's most likely caused by the client disconnecting.
// However, if it was cancelled for any other reason we need to prevent empty responses.
_context.Abort();
}
}

Expand Down Expand Up @@ -400,20 +406,26 @@ internal async Task SendRangeAsync()
if (sendFile != null && !string.IsNullOrEmpty(physicalPath))
{
_logger.LogSendingFileRange(_response.Headers[HeaderNames.ContentRange], physicalPath);
await sendFile.SendFileAsync(physicalPath, start, length, _context.RequestAborted);
// We don't need to directly cancel this, if the client disconnects it will fail silently.
await sendFile.SendFileAsync(physicalPath, start, length, CancellationToken.None);
return;
}

Stream readStream = _fileInfo.CreateReadStream();
try
{
readStream.Seek(start, SeekOrigin.Begin); // TODO: What if !CanSeek?
_logger.LogCopyingFileRange(_response.Headers[HeaderNames.ContentRange], SubPath);
await StreamCopyOperation.CopyToAsync(readStream, _response.Body, length, _context.RequestAborted);
using (var readStream = _fileInfo.CreateReadStream())
{
readStream.Seek(start, SeekOrigin.Begin); // TODO: What if !CanSeek?
_logger.LogCopyingFileRange(_response.Headers[HeaderNames.ContentRange], SubPath);
await StreamCopyOperation.CopyToAsync(readStream, _response.Body, length, _context.RequestAborted);
}
}
finally
catch (OperationCanceledException ex)
{
readStream.Dispose();
_logger.LogWriteCancelled(ex);
// Don't throw this exception, it's most likely caused by the client disconnecting.
// However, if it was cancelled for any other reason we need to prevent empty responses.
_context.Abort();
}
}

Expand Down

0 comments on commit 83d7963

Please sign in to comment.