Remove GetService calls in Static Files

This commit is contained in:
Hao Kung 2016-03-04 15:16:21 -08:00
parent f78abb5bcf
commit 2f7e31ab5b
17 changed files with 64 additions and 76 deletions

View File

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;
@ -21,6 +22,7 @@ namespace Microsoft.AspNetCore.StaticFiles
private readonly DefaultFilesOptions _options;
private readonly PathString _matchUrl;
private readonly RequestDelegate _next;
private readonly IFileProvider _fileProvider;
/// <summary>
/// Creates a new instance of the DefaultFilesMiddleware.
@ -47,7 +49,7 @@ namespace Microsoft.AspNetCore.StaticFiles
_next = next;
_options = options.Value;
_options.ResolveFileProvider(hostingEnv);
_fileProvider = _options.FileProvider ?? Helpers.ResolveFileProvider(hostingEnv);
_matchUrl = _options.RequestPath;
}
@ -64,14 +66,14 @@ namespace Microsoft.AspNetCore.StaticFiles
if (Helpers.IsGetOrHeadMethod(context.Request.Method)
&& Helpers.TryMatchPath(context, _matchUrl, forDirectory: true, subpath: out subpath))
{
var dirContents = _options.FileProvider.GetDirectoryContents(subpath.Value);
var dirContents = _fileProvider.GetDirectoryContents(subpath.Value);
if (dirContents.Exists)
{
// Check if any of our default files exist.
for (int matchIndex = 0; matchIndex < _options.DefaultFileNames.Count; matchIndex++)
{
string defaultFile = _options.DefaultFileNames[matchIndex];
var file = _options.FileProvider.GetFileInfo(subpath + defaultFile);
var file = _fileProvider.GetFileInfo(subpath + defaultFile);
// TryMatchPath will make sure subpath always ends with a "/" by adding it if needed.
if (file.Exists)
{

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Builder
/// <summary>
/// Options for selecting default file names.
/// </summary>
public class DefaultFilesOptions : SharedOptionsBase<DefaultFilesOptions>
public class DefaultFilesOptions : SharedOptionsBase
{
/// <summary>
/// Configuration for the DefaultFilesMiddleware.

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
@ -20,14 +21,17 @@ namespace Microsoft.AspNetCore.StaticFiles
private readonly DirectoryBrowserOptions _options;
private readonly PathString _matchUrl;
private readonly RequestDelegate _next;
private readonly IDirectoryFormatter _formatter;
private readonly IFileProvider _fileProvider;
/// <summary>
/// Creates a new instance of the SendFileMiddleware.
/// </summary>
/// <param name="next">The next middleware in the pipeline.</param>
/// <param name="hostingEnv">The <see cref="IHostingEnvironment"/> used by this middleware.</param>
/// <param name="encoder">The <see cref="HtmlEncoder"/> used by the default <see cref="HtmlDirectoryFormatter"/>.</param>
/// <param name="options">The configuration for this middleware.</param>
public DirectoryBrowserMiddleware(RequestDelegate next, IHostingEnvironment hostingEnv, IOptions<DirectoryBrowserOptions> options)
public DirectoryBrowserMiddleware(RequestDelegate next, IHostingEnvironment hostingEnv, HtmlEncoder encoder, IOptions<DirectoryBrowserOptions> options)
{
if (next == null)
{
@ -39,19 +43,20 @@ namespace Microsoft.AspNetCore.StaticFiles
throw new ArgumentNullException(nameof(hostingEnv));
}
if (encoder == null)
{
throw new ArgumentNullException(nameof(encoder));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
if (options.Value.Formatter == null)
{
throw new ArgumentException(Resources.Args_NoFormatter);
}
_next = next;
_options = options.Value;
_options.ResolveFileProvider(hostingEnv);
_fileProvider = _options.FileProvider ?? Helpers.ResolveFileProvider(hostingEnv);
_formatter = options.Value.Formatter ?? new HtmlDirectoryFormatter(encoder);
_matchUrl = _options.RequestPath;
}
@ -78,7 +83,7 @@ namespace Microsoft.AspNetCore.StaticFiles
return Constants.CompletedTask;
}
return _options.Formatter.GenerateContentAsync(context, contents);
return _formatter.GenerateContentAsync(context, contents);
}
return _next(context);
@ -86,7 +91,7 @@ namespace Microsoft.AspNetCore.StaticFiles
private bool TryGetDirectoryInfo(PathString subpath, out IDirectoryContents contents)
{
contents = _options.FileProvider.GetDirectoryContents(subpath.Value);
contents = _fileProvider.GetDirectoryContents(subpath.Value);
return contents.Exists;
}
}

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Builder
/// <summary>
/// Directory browsing options
/// </summary>
public class DirectoryBrowserOptions : SharedOptionsBase<DirectoryBrowserOptions>
public class DirectoryBrowserOptions : SharedOptionsBase
{
/// <summary>
/// Enabled directory browsing for all request paths
@ -26,7 +26,6 @@ namespace Microsoft.AspNetCore.Builder
public DirectoryBrowserOptions(SharedOptions sharedOptions)
: base(sharedOptions)
{
Formatter = new HtmlDirectoryFormatter();
}
/// <summary>

View File

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Microsoft.AspNetCore.StaticFiles
{

View File

@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Builder
/// <summary>
/// Options for all of the static file middleware components
/// </summary>
public class FileServerOptions : SharedOptionsBase<FileServerOptions>
public class FileServerOptions : SharedOptionsBase
{
/// <summary>
/// Creates a combined options class for all of the static file middleware components.

View File

@ -2,12 +2,23 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
namespace Microsoft.AspNetCore.StaticFiles
{
internal static class Helpers
{
internal static IFileProvider ResolveFileProvider(IHostingEnvironment hostingEnv)
{
if (hostingEnv.WebRootFileProvider == null) {
throw new InvalidOperationException("Missing FileProvider.");
}
return hostingEnv.WebRootFileProvider;
}
internal static bool IsGetOrHeadMethod(string method)
{
return IsGetMethod(method) || IsHeadMethod(method);

View File

@ -23,6 +23,15 @@ namespace Microsoft.AspNetCore.StaticFiles
private HtmlEncoder _htmlEncoder;
public HtmlDirectoryFormatter(HtmlEncoder encoder)
{
if (encoder == null)
{
throw new ArgumentNullException(nameof(encoder));
}
_htmlEncoder = encoder;
}
/// <summary>
/// Generates an HTML view for a directory.
/// </summary>
@ -37,11 +46,6 @@ namespace Microsoft.AspNetCore.StaticFiles
throw new ArgumentNullException(nameof(contents));
}
if (_htmlEncoder == null)
{
_htmlEncoder = context.RequestServices.GetRequiredService<HtmlEncoder>();
}
context.Response.ContentType = TextHtmlUtf8;
if (Helpers.IsHeadMethod(context.Request.Method))

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
@ -11,8 +10,7 @@ namespace Microsoft.AspNetCore.StaticFiles.Infrastructure
/// <summary>
/// Options common to several middleware components
/// </summary>
/// <typeparam name="T">The type of the subclass</typeparam>
public abstract class SharedOptionsBase<T>
public abstract class SharedOptionsBase
{
/// <summary>
/// Creates an new instance of the SharedOptionsBase.
@ -50,17 +48,5 @@ namespace Microsoft.AspNetCore.StaticFiles.Infrastructure
get { return SharedOptions.FileProvider; }
set { SharedOptions.FileProvider = value; }
}
internal void ResolveFileProvider(IHostingEnvironment hostingEnv)
{
if (FileProvider == null)
{
FileProvider = hostingEnv.WebRootFileProvider;
if (FileProvider == null)
{
throw new InvalidOperationException("Missing FileProvider.");
}
}
}
}
}

View File

@ -10,22 +10,6 @@ namespace Microsoft.AspNetCore.StaticFiles
private static readonly ResourceManager _resourceManager
= new ResourceManager("Microsoft.AspNetCore.StaticFiles.Resources", typeof(Resources).GetTypeInfo().Assembly);
/// <summary>
/// No IContentTypeProvider was specified.
/// </summary>
internal static string Args_NoContentTypeProvider
{
get { return GetString("Args_NoContentTypeProvider"); }
}
/// <summary>
/// No IContentTypeProvider was specified.
/// </summary>
internal static string FormatArgs_NoContentTypeProvider()
{
return GetString("Args_NoContentTypeProvider");
}
/// <summary>
/// No formatter provided.
/// </summary>

View File

@ -117,9 +117,6 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Args_NoContentTypeProvider" xml:space="preserve">
<value>No IContentTypeProvider was specified.</value>
</data>
<data name="Args_NoFormatter" xml:space="preserve">
<value>No formatter provided.</value>
</data>

View File

@ -27,6 +27,8 @@ namespace Microsoft.AspNetCore.StaticFiles
private readonly HttpRequest _request;
private readonly HttpResponse _response;
private readonly ILogger _logger;
private readonly IFileProvider _fileProvider;
private readonly IContentTypeProvider _contentTypeProvider;
private string _method;
private bool _isGet;
private bool _isHead;
@ -47,7 +49,7 @@ namespace Microsoft.AspNetCore.StaticFiles
private IList<RangeItemHeaderValue> _ranges;
public StaticFileContext(HttpContext context, StaticFileOptions options, PathString matchUrl, ILogger logger)
public StaticFileContext(HttpContext context, StaticFileOptions options, PathString matchUrl, ILogger logger, IFileProvider fileProvider, IContentTypeProvider contentTypeProvider)
{
_context = context;
_options = options;
@ -57,6 +59,8 @@ namespace Microsoft.AspNetCore.StaticFiles
_logger = logger;
_requestHeaders = _request.GetTypedHeaders();
_responseHeaders = _response.GetTypedHeaders();
_fileProvider = fileProvider;
_contentTypeProvider = contentTypeProvider;
_method = null;
_isGet = false;
@ -118,7 +122,7 @@ namespace Microsoft.AspNetCore.StaticFiles
public bool LookupContentType()
{
if (_options.ContentTypeProvider.TryGetContentType(_subPath.Value, out _contentType))
if (_contentTypeProvider.TryGetContentType(_subPath.Value, out _contentType))
{
return true;
}
@ -134,7 +138,7 @@ namespace Microsoft.AspNetCore.StaticFiles
public bool LookupFileInfo()
{
_fileInfo = _options.FileProvider.GetFileInfo(_subPath.Value);
_fileInfo = _fileProvider.GetFileInfo(_subPath.Value);
if (_fileInfo.Exists)
{
_length = _fileInfo.Length;

View File

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@ -21,6 +22,8 @@ namespace Microsoft.AspNetCore.StaticFiles
private readonly PathString _matchUrl;
private readonly RequestDelegate _next;
private readonly ILogger _logger;
private readonly IFileProvider _fileProvider;
private readonly IContentTypeProvider _contentTypeProvider;
/// <summary>
/// Creates a new instance of the StaticFileMiddleware.
@ -51,14 +54,10 @@ namespace Microsoft.AspNetCore.StaticFiles
throw new ArgumentNullException(nameof(loggerFactory));
}
if (options.Value.ContentTypeProvider == null)
{
throw new ArgumentException(Resources.Args_NoContentTypeProvider);
}
_next = next;
_options = options.Value;
_options.ResolveFileProvider(hostingEnv);
_contentTypeProvider = options.Value.ContentTypeProvider ?? new FileExtensionContentTypeProvider();
_fileProvider = _options.FileProvider ?? Helpers.ResolveFileProvider(hostingEnv);
_matchUrl = _options.RequestPath;
_logger = loggerFactory.CreateLogger<StaticFileMiddleware>();
}
@ -70,7 +69,7 @@ namespace Microsoft.AspNetCore.StaticFiles
/// <returns></returns>
public Task Invoke(HttpContext context)
{
var fileContext = new StaticFileContext(context, _options, _matchUrl, _logger);
var fileContext = new StaticFileContext(context, _options, _matchUrl, _logger, _fileProvider, _contentTypeProvider);
if (!fileContext.ValidateMethod())
{

View File

@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Builder
/// <summary>
/// Options for serving static files
/// </summary>
public class StaticFileOptions : SharedOptionsBase<StaticFileOptions>
public class StaticFileOptions : SharedOptionsBase
{
/// <summary>
/// Defaults to all request paths
@ -25,8 +25,6 @@ namespace Microsoft.AspNetCore.Builder
/// <param name="sharedOptions"></param>
public StaticFileOptions(SharedOptions sharedOptions) : base(sharedOptions)
{
ContentTypeProvider = new FileExtensionContentTypeProvider();
OnPrepareResponse = _ => { };
}

View File

@ -22,9 +22,10 @@ namespace Microsoft.AspNetCore.StaticFiles
[Fact]
public async Task NullArguments()
{
Assert.Throws<ArgumentException>(() => StaticFilesTestServer.Create(
// No exception, default provided
StaticFilesTestServer.Create(
app => app.UseDirectoryBrowser(new DirectoryBrowserOptions { Formatter = null }),
services => services.AddDirectoryBrowser()));
services => services.AddDirectoryBrowser());
// No exception, default provided
StaticFilesTestServer.Create(

View File

@ -21,8 +21,7 @@ namespace Microsoft.AspNetCore.StaticFiles
{
// Arrange
var options = new StaticFileOptions();
options.FileProvider = new TestFileProvider();
var context = new StaticFileContext(new DefaultHttpContext(), options, PathString.Empty, NullLogger.Instance);
var context = new StaticFileContext(new DefaultHttpContext(), options, PathString.Empty, NullLogger.Instance, new TestFileProvider(), new FileExtensionContentTypeProvider());
// Act
var validateResult = context.ValidatePath();
@ -43,11 +42,10 @@ namespace Microsoft.AspNetCore.StaticFiles
{
LastModified = new DateTimeOffset(2014, 1, 2, 3, 4, 5, TimeSpan.Zero)
});
options.FileProvider = fileProvider;
var pathString = new PathString("/test");
var httpContext = new DefaultHttpContext();
httpContext.Request.Path = new PathString("/test/foo.txt");
var context = new StaticFileContext(httpContext, options, pathString, NullLogger.Instance);
var context = new StaticFileContext(httpContext, options, pathString, NullLogger.Instance, fileProvider, new FileExtensionContentTypeProvider());
// Act
context.ValidatePath();

View File

@ -32,7 +32,8 @@ namespace Microsoft.AspNetCore.StaticFiles
[Fact]
public async Task NullArguments()
{
Assert.Throws<ArgumentException>(() => StaticFilesTestServer.Create(app => app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = null })));
// No exception, default provided
StaticFilesTestServer.Create(app => app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = null }));
// No exception, default provided
StaticFilesTestServer.Create(app => app.UseStaticFiles(new StaticFileOptions { FileProvider = null }));