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

Commit bbf1478

Browse files
committed
#150 Handle OperationCancelledExceptions to prevent log noise
1 parent df66f51 commit bbf1478

File tree

15 files changed

+385
-16
lines changed

15 files changed

+385
-16
lines changed

StaticFiles.sln

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
21
Microsoft Visual Studio Solution File, Format Version 12.00
32
# Visual Studio 14
4-
VisualStudioVersion = 14.0.21916.0
3+
VisualStudioVersion = 14.0.25420.1
54
MinimumVisualStudioVersion = 10.0.40219.1
65
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{40EE0889-960E-41B4-A3D3-9CE963EB0797}"
76
EndProject
@@ -20,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
2019
global.json = global.json
2120
EndProjectSection
2221
EndProject
22+
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.StaticFiles.FunctionalTests", "test\Microsoft.AspNetCore.StaticFiles.FunctionalTests\Microsoft.AspNetCore.StaticFiles.FunctionalTests.xproj", "{FDF0539C-1F62-4B78-91B1-C687886931CA}"
23+
EndProject
2324
Global
2425
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2526
Debug|Any CPU = Debug|Any CPU
@@ -60,6 +61,18 @@ Global
6061
{CC87FE7D-8F42-4BE9-A152-9625E837C1E5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
6162
{CC87FE7D-8F42-4BE9-A152-9625E837C1E5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
6263
{CC87FE7D-8F42-4BE9-A152-9625E837C1E5}.Release|x86.ActiveCfg = Release|Any CPU
64+
{FDF0539C-1F62-4B78-91B1-C687886931CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
65+
{FDF0539C-1F62-4B78-91B1-C687886931CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
66+
{FDF0539C-1F62-4B78-91B1-C687886931CA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
67+
{FDF0539C-1F62-4B78-91B1-C687886931CA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
68+
{FDF0539C-1F62-4B78-91B1-C687886931CA}.Debug|x86.ActiveCfg = Debug|Any CPU
69+
{FDF0539C-1F62-4B78-91B1-C687886931CA}.Debug|x86.Build.0 = Debug|Any CPU
70+
{FDF0539C-1F62-4B78-91B1-C687886931CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
71+
{FDF0539C-1F62-4B78-91B1-C687886931CA}.Release|Any CPU.Build.0 = Release|Any CPU
72+
{FDF0539C-1F62-4B78-91B1-C687886931CA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
73+
{FDF0539C-1F62-4B78-91B1-C687886931CA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
74+
{FDF0539C-1F62-4B78-91B1-C687886931CA}.Release|x86.ActiveCfg = Release|Any CPU
75+
{FDF0539C-1F62-4B78-91B1-C687886931CA}.Release|x86.Build.0 = Release|Any CPU
6376
EndGlobalSection
6477
GlobalSection(SolutionProperties) = preSolution
6578
HideSolutionNode = FALSE
@@ -68,5 +81,6 @@ Global
6881
{8D7BC5A4-F19C-4184-8338-A6B42997218C} = {40EE0889-960E-41B4-A3D3-9CE963EB0797}
6982
{092141D9-305A-4FC5-AE74-CB23982CA8D4} = {8B21A3A9-9CA6-4857-A6E0-1A3203404B60}
7083
{CC87FE7D-8F42-4BE9-A152-9625E837C1E5} = {EF02AFE8-7C15-4DDB-8B2C-58A676112A98}
84+
{FDF0539C-1F62-4B78-91B1-C687886931CA} = {EF02AFE8-7C15-4DDB-8B2C-58A676112A98}
7185
EndGlobalSection
7286
EndGlobal

src/Microsoft.AspNetCore.StaticFiles/LoggerExtensions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ internal static class LoggerExtensions
2525
private static Action<ILogger, StringValues, string, Exception> _logCopyingFileRange;
2626
private static Action<ILogger, long, string, string, Exception> _logCopyingBytesToResponse;
2727
private static Action<ILogger, string, Exception> _logMultipleFileRanges;
28+
private static Action<ILogger, Exception> _logWriteCancelled;
2829

2930
static LoggerExtensions()
3031
{
@@ -80,6 +81,10 @@ static LoggerExtensions()
8081
logLevel: LogLevel.Warning,
8182
eventId: 13,
8283
formatString: "Multiple ranges are not allowed: '{Ranges}'");
84+
_logWriteCancelled = LoggerMessage.Define(
85+
logLevel: LogLevel.Debug,
86+
eventId: 14,
87+
formatString: "The file transmission was cancelled");
8388
}
8489

8590
public static void LogRequestMethodNotSupported(this ILogger logger, string method)
@@ -155,5 +160,10 @@ public static void LogMultipleFileRanges(this ILogger logger, string range)
155160
{
156161
_logMultipleFileRanges(logger, range, null);
157162
}
163+
164+
public static void LogWriteCancelled(this ILogger logger, Exception ex)
165+
{
166+
_logWriteCancelled(logger, ex);
167+
}
158168
}
159169
}

src/Microsoft.AspNetCore.StaticFiles/StaticFileContext.cs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Diagnostics;
77
using System.IO;
88
using System.Linq;
9+
using System.Threading;
910
using System.Threading.Tasks;
1011
using Microsoft.AspNetCore.Builder;
1112
using Microsoft.AspNetCore.Http;
@@ -345,24 +346,29 @@ public Task SendStatusAsync(int statusCode)
345346
public async Task SendAsync()
346347
{
347348
ApplyResponseHeaders(Constants.Status200Ok);
348-
349349
string physicalPath = _fileInfo.PhysicalPath;
350350
var sendFile = _context.Features.Get<IHttpSendFileFeature>();
351351
if (sendFile != null && !string.IsNullOrEmpty(physicalPath))
352352
{
353-
await sendFile.SendFileAsync(physicalPath, 0, _length, _context.RequestAborted);
353+
// We don't need to directly cancel this, if the client disconnects it will fail silently.
354+
await sendFile.SendFileAsync(physicalPath, 0, _length, CancellationToken.None);
354355
return;
355356
}
356357

357-
Stream readStream = _fileInfo.CreateReadStream();
358358
try
359359
{
360-
// Larger StreamCopyBufferSize is required because in case of FileStream readStream isn't going to be buffering
361-
await StreamCopyOperation.CopyToAsync(readStream, _response.Body, _length, StreamCopyBufferSize, _context.RequestAborted);
360+
using (var readStream = _fileInfo.CreateReadStream())
361+
{
362+
// Larger StreamCopyBufferSize is required because in case of FileStream readStream isn't going to be buffering
363+
await StreamCopyOperation.CopyToAsync(readStream, _response.Body, _length, StreamCopyBufferSize, _context.RequestAborted);
364+
}
362365
}
363-
finally
366+
catch (OperationCanceledException ex)
364367
{
365-
readStream.Dispose();
368+
_logger.LogWriteCancelled(ex);
369+
// Don't throw this exception, it's most likely caused by the client disconnecting.
370+
// However, if it was cancelled for any other reason we need to prevent empty responses.
371+
_context.Abort();
366372
}
367373
}
368374

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

407-
Stream readStream = _fileInfo.CreateReadStream();
408414
try
409415
{
410-
readStream.Seek(start, SeekOrigin.Begin); // TODO: What if !CanSeek?
411-
_logger.LogCopyingFileRange(_response.Headers[HeaderNames.ContentRange], SubPath);
412-
await StreamCopyOperation.CopyToAsync(readStream, _response.Body, length, _context.RequestAborted);
416+
using (var readStream = _fileInfo.CreateReadStream())
417+
{
418+
readStream.Seek(start, SeekOrigin.Begin); // TODO: What if !CanSeek?
419+
_logger.LogCopyingFileRange(_response.Headers[HeaderNames.ContentRange], SubPath);
420+
await StreamCopyOperation.CopyToAsync(readStream, _response.Body, length, _context.RequestAborted);
421+
}
413422
}
414-
finally
423+
catch (OperationCanceledException ex)
415424
{
416-
readStream.Dispose();
425+
_logger.LogWriteCancelled(ex);
426+
// Don't throw this exception, it's most likely caused by the client disconnecting.
427+
// However, if it was cancelled for any other reason we need to prevent empty responses.
428+
_context.Abort();
417429
}
418430
}
419431

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
5+
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
6+
</PropertyGroup>
7+
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
8+
<PropertyGroup Label="Globals">
9+
<ProjectGuid>fdf0539c-1f62-4b78-91b1-c687886931ca</ProjectGuid>
10+
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
11+
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
12+
</PropertyGroup>
13+
<PropertyGroup>
14+
<SchemaVersion>2.0</SchemaVersion>
15+
</PropertyGroup>
16+
<ItemGroup>
17+
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
18+
</ItemGroup>
19+
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
20+
</Project>

0 commit comments

Comments
 (0)