diff --git a/samples/StaticFileSample/Startup.cs b/samples/StaticFileSample/Startup.cs index a6337fe7d6..ba73533790 100644 --- a/samples/StaticFileSample/Startup.cs +++ b/samples/StaticFileSample/Startup.cs @@ -1,13 +1,18 @@ using Microsoft.AspNet.Builder; using Microsoft.AspNet.FileSystems; using Microsoft.AspNet.StaticFiles; +using Microsoft.Framework.Logging; +using Microsoft.Framework.Logging.Console; namespace StaticFilesSample { public class Startup { - public void Configure(IApplicationBuilder app) + public void Configure(IApplicationBuilder app, ILoggerFactory factory) { + // Displays all log levels + factory.AddConsole(LogLevel.Verbose); + app.UseFileServer(new FileServerOptions() { EnableDirectoryBrowsing = true, diff --git a/samples/StaticFileSample/StaticFileSample.kproj b/samples/StaticFileSample/StaticFileSample.kproj index 2ebbf8a0b5..c83664fd1b 100644 --- a/samples/StaticFileSample/StaticFileSample.kproj +++ b/samples/StaticFileSample/StaticFileSample.kproj @@ -12,6 +12,7 @@ 2.0 + 16758 diff --git a/samples/StaticFileSample/project.json b/samples/StaticFileSample/project.json index 0b07dc6047..a0f2cf42d2 100644 --- a/samples/StaticFileSample/project.json +++ b/samples/StaticFileSample/project.json @@ -3,10 +3,11 @@ "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.Urls http://localhost:12345/" }, "dependencies": { + "Kestrel": "1.0.0-*", "Microsoft.AspNet.Server.IIS": "1.0.0-*", "Microsoft.AspNet.Server.WebListener": "1.0.0-*", - "Kestrel": "1.0.0-*", - "Microsoft.AspNet.StaticFiles": "1.0.0-*" + "Microsoft.AspNet.StaticFiles": "1.0.0-*", + "Microsoft.Framework.Logging.Console": "1.0.0-*" }, "frameworks": { "aspnet50": { }, diff --git a/src/Microsoft.AspNet.StaticFiles/SendFileMiddleware.cs b/src/Microsoft.AspNet.StaticFiles/SendFileMiddleware.cs index 8351dcd3a3..3bc14fa70a 100644 --- a/src/Microsoft.AspNet.StaticFiles/SendFileMiddleware.cs +++ b/src/Microsoft.AspNet.StaticFiles/SendFileMiddleware.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.AspNet.Builder; using Microsoft.AspNet.Http; using Microsoft.AspNet.HttpFeature; +using Microsoft.Framework.Logging; namespace Microsoft.AspNet.StaticFiles { @@ -20,14 +21,17 @@ namespace Microsoft.AspNet.StaticFiles public class SendFileMiddleware { private readonly RequestDelegate _next; + private readonly ILogger _logger; /// /// Creates a new instance of the SendFileMiddleware. /// /// The next middleware in the pipeline. - public SendFileMiddleware([NotNull] RequestDelegate next) + /// An instance used to create loggers. + public SendFileMiddleware([NotNull] RequestDelegate next, [NotNull] ILoggerFactory loggerFactory) { _next = next; + _logger = loggerFactory.Create(); } public Task Invoke(HttpContext context) @@ -35,7 +39,7 @@ namespace Microsoft.AspNet.StaticFiles // Check if there is a SendFile feature already present if (context.GetFeature() == null) { - context.SetFeature(new SendFileWrapper(context.Response.Body)); + context.SetFeature(new SendFileWrapper(context.Response.Body, _logger)); } return _next(context); @@ -44,10 +48,12 @@ namespace Microsoft.AspNet.StaticFiles private class SendFileWrapper : IHttpSendFileFeature { private readonly Stream _output; + private readonly ILogger _logger; - internal SendFileWrapper(Stream output) + internal SendFileWrapper(Stream output, ILogger logger) { _output = output; + _logger = logger; } // Not safe for overlapped writes. @@ -86,6 +92,10 @@ namespace Microsoft.AspNet.StaticFiles try { fileStream.Seek(offset, SeekOrigin.Begin); + if (_logger.IsEnabled(LogLevel.Verbose)) + { + _logger.WriteVerbose(string.Format("Copying bytes {0}-{1} of file {2} to response body", offset, length != null ? (offset + length).ToString() : "*", fileName)); + } await StreamCopyOperation.CopyToAsync(fileStream, _output, length, cancel); } finally diff --git a/src/Microsoft.AspNet.StaticFiles/StaticFileContext.cs b/src/Microsoft.AspNet.StaticFiles/StaticFileContext.cs index 06b6311338..1028a8fb59 100644 --- a/src/Microsoft.AspNet.StaticFiles/StaticFileContext.cs +++ b/src/Microsoft.AspNet.StaticFiles/StaticFileContext.cs @@ -11,6 +11,7 @@ using Microsoft.AspNet.FileSystems; using Microsoft.AspNet.Http; using Microsoft.AspNet.HttpFeature; using Microsoft.AspNet.StaticFiles.Infrastructure; +using Microsoft.Framework.Logging; namespace Microsoft.AspNet.StaticFiles { @@ -21,6 +22,7 @@ namespace Microsoft.AspNet.StaticFiles private readonly PathString _matchUrl; private readonly HttpRequest _request; private readonly HttpResponse _response; + private readonly ILogger _logger; private string _method; private bool _isGet; private bool _isHead; @@ -40,13 +42,14 @@ namespace Microsoft.AspNet.StaticFiles private IList> _ranges; - public StaticFileContext(HttpContext context, StaticFileOptions options, PathString matchUrl) + public StaticFileContext(HttpContext context, StaticFileOptions options, PathString matchUrl, ILogger logger) { _context = context; _options = options; _matchUrl = matchUrl; _request = context.Request; _response = context.Response; + _logger = logger; _method = null; _isGet = false; @@ -83,6 +86,11 @@ namespace Microsoft.AspNet.StaticFiles { get { return _ranges != null; } } + + public string SubPath + { + get { return _subPath.Value; } + } public bool ValidateMethod() { @@ -220,6 +228,7 @@ namespace Microsoft.AspNet.StaticFiles if (ranges.Count > 1) { // multiple range headers not yet supported + _logger.WriteWarning("Multiple range headers not yet supported, {0} ranges in header", ranges.Count.ToString()); return; } @@ -308,6 +317,10 @@ namespace Microsoft.AspNet.StaticFiles { ApplyResponseHeaders(statusCode); + if (_logger.IsEnabled(LogLevel.Verbose)) + { + _logger.WriteVerbose(string.Format("Handled. Status code: {0} File: {1}", statusCode, SubPath)); + } return Constants.CompletedTask; } @@ -350,6 +363,7 @@ namespace Microsoft.AspNet.StaticFiles // the current length of the selected resource. e.g. */length _response.Headers[Constants.ContentRange] = "bytes */" + _length.ToString(CultureInfo.InvariantCulture); ApplyResponseHeaders(Constants.Status416RangeNotSatisfiable); + _logger.WriteWarning("Range not satisfiable for {0}", SubPath); return; } @@ -365,6 +379,10 @@ namespace Microsoft.AspNet.StaticFiles var sendFile = _context.GetFeature(); if (sendFile != null && !string.IsNullOrEmpty(physicalPath)) { + if (_logger.IsEnabled(LogLevel.Verbose)) + { + _logger.WriteVerbose(string.Format("Sending {0} of file {1}", _response.Headers[Constants.ContentRange], physicalPath)); + } await sendFile.SendFileAsync(physicalPath, start, length, _context.RequestAborted); return; } @@ -373,6 +391,10 @@ namespace Microsoft.AspNet.StaticFiles try { readStream.Seek(start, SeekOrigin.Begin); // TODO: What if !CanSeek? + if (_logger.IsEnabled(LogLevel.Verbose)) + { + _logger.WriteVerbose(string.Format("Copying {0} of file {1} to the response body", _response.Headers[Constants.ContentRange], SubPath)); + } await StreamCopyOperation.CopyToAsync(readStream, _response.Body, length, _context.RequestAborted); } finally diff --git a/src/Microsoft.AspNet.StaticFiles/StaticFileMiddleware.cs b/src/Microsoft.AspNet.StaticFiles/StaticFileMiddleware.cs index a630f367f2..a9c09d84b3 100644 --- a/src/Microsoft.AspNet.StaticFiles/StaticFileMiddleware.cs +++ b/src/Microsoft.AspNet.StaticFiles/StaticFileMiddleware.cs @@ -7,6 +7,7 @@ using Microsoft.AspNet.Builder; using Microsoft.AspNet.FileSystems; using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Http; +using Microsoft.Framework.Logging; namespace Microsoft.AspNet.StaticFiles { @@ -18,13 +19,15 @@ namespace Microsoft.AspNet.StaticFiles private readonly StaticFileOptions _options; private readonly PathString _matchUrl; private readonly RequestDelegate _next; + private readonly ILogger _logger; /// /// Creates a new instance of the StaticFileMiddleware. /// /// The next middleware in the pipeline. /// The configuration options. - public StaticFileMiddleware([NotNull] RequestDelegate next, [NotNull] IHostingEnvironment hostingEnv, [NotNull] StaticFileOptions options) + /// An instance used to create loggers. + public StaticFileMiddleware([NotNull] RequestDelegate next, [NotNull] IHostingEnvironment hostingEnv, [NotNull] StaticFileOptions options, [NotNull] ILoggerFactory loggerFactory) { if (options.ContentTypeProvider == null) { @@ -35,6 +38,7 @@ namespace Microsoft.AspNet.StaticFiles _next = next; _options = options; _matchUrl = options.RequestPath; + _logger = loggerFactory.Create(); } /// @@ -44,7 +48,7 @@ namespace Microsoft.AspNet.StaticFiles /// public Task Invoke(HttpContext context) { - var fileContext = new StaticFileContext(context, _options, _matchUrl); + var fileContext = new StaticFileContext(context, _options, _matchUrl, _logger); if (fileContext.ValidateMethod() && fileContext.ValidatePath() && fileContext.LookupContentType() @@ -64,16 +68,26 @@ namespace Microsoft.AspNet.StaticFiles { return fileContext.SendRangeAsync(); } + if (_logger.IsEnabled(LogLevel.Verbose)) + { + _logger.WriteVerbose(string.Format("Copying file {0} to the response body", fileContext.SubPath)); + } return fileContext.SendAsync(); case StaticFileContext.PreconditionState.NotModified: + if (_logger.IsEnabled(LogLevel.Verbose)) + { + _logger.WriteVerbose(string.Format("{0} not modified", fileContext.SubPath)); + } return fileContext.SendStatusAsync(Constants.Status304NotModified); case StaticFileContext.PreconditionState.PreconditionFailed: return fileContext.SendStatusAsync(Constants.Status412PreconditionFailed); default: - throw new NotImplementedException(fileContext.GetPreconditionState().ToString()); + var exception = new NotImplementedException(fileContext.GetPreconditionState().ToString()); + _logger.WriteError("No precondition state specified", exception); + throw exception; } } diff --git a/src/Microsoft.AspNet.StaticFiles/project.json b/src/Microsoft.AspNet.StaticFiles/project.json index 32b6764bb5..aa56171bce 100644 --- a/src/Microsoft.AspNet.StaticFiles/project.json +++ b/src/Microsoft.AspNet.StaticFiles/project.json @@ -6,7 +6,8 @@ "Microsoft.AspNet.Hosting": { "version": "1.0.0-*", "type": "build" }, "Microsoft.AspNet.Http": "1.0.0-*", "Microsoft.AspNet.Http.Extensions": "1.0.0-*", - "Microsoft.AspNet.HttpFeature": { "version": "1.0.0-*", "type": "build" } + "Microsoft.AspNet.HttpFeature": { "version": "1.0.0-*", "type": "build" }, + "Microsoft.Framework.Logging": "1.0.0-*" }, "frameworks": { "aspnet50": { },