// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System; using System.Threading.Tasks; using Microsoft.AspNet.Abstractions; using Microsoft.Owin.FileSystems; namespace Microsoft.AspNet.StaticFiles { /// /// Enables serving static files for a given request path /// public class StaticFileMiddleware { private readonly StaticFileOptions _options; private readonly PathString _matchUrl; private readonly RequestDelegate _next; /// /// Creates a new instance of the StaticFileMiddleware. /// /// The next middleware in the pipeline. /// The configuration options. public StaticFileMiddleware(RequestDelegate next, StaticFileOptions options) { if (next == null) { throw new ArgumentNullException("next"); } if (options == null) { throw new ArgumentNullException("options"); } if (options.ContentTypeProvider == null) { throw new ArgumentException(Resources.Args_NoContentTypeProvider); } if (options.FileSystem == null) { options.FileSystem = new PhysicalFileSystem("." + options.RequestPath.Value); } _next = next; _options = options; _matchUrl = options.RequestPath; } /// /// Processes a request to determine if it matches a known file, and if so, serves it. /// /// /// public Task Invoke(HttpContext context) { var fileContext = new StaticFileContext(context, _options, _matchUrl); if (fileContext.ValidateMethod() && fileContext.ValidatePath() && fileContext.LookupContentType() && fileContext.LookupFileInfo()) { fileContext.ComprehendRequestHeaders(); switch (fileContext.GetPreconditionState()) { case StaticFileContext.PreconditionState.Unspecified: case StaticFileContext.PreconditionState.ShouldProcess: if (fileContext.IsHeadMethod) { return fileContext.SendStatusAsync(Constants.Status200Ok); } if (fileContext.IsRangeRequest) { return fileContext.SendRangeAsync(); } return fileContext.SendAsync(); case StaticFileContext.PreconditionState.NotModified: return fileContext.SendStatusAsync(Constants.Status304NotModified); case StaticFileContext.PreconditionState.PreconditionFailed: return fileContext.SendStatusAsync(Constants.Status412PreconditionFailed); default: throw new NotImplementedException(fileContext.GetPreconditionState().ToString()); } } return _next(context); } } }