Allow explicit configuration of StaticFileOptions in new SPA APIs. Fixes #1424.

This commit is contained in:
Steve Sanderson
2018-01-02 15:44:59 +00:00
parent 814441c933
commit 15d2f5a898
3 changed files with 51 additions and 28 deletions

View File

@@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.SpaServices
// Developers who need to host more than one SPA with distinct default pages can // Developers who need to host more than one SPA with distinct default pages can
// override the file provider // override the file provider
app.UseSpaStaticFilesInternal( app.UseSpaStaticFilesInternal(
overrideFileProvider: options.DefaultPageFileProvider, options.DefaultPageStaticFileOptions ?? new StaticFileOptions(),
allowFallbackOnServingWebRootFiles: true); allowFallbackOnServingWebRootFiles: true);
// If the default file didn't get served as a static file (usually because it was not // If the default file didn't get served as a static file (usually because it was not

View File

@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders;
@@ -29,7 +30,7 @@ namespace Microsoft.AspNetCore.SpaServices
internal SpaOptions(SpaOptions copyFromOptions) internal SpaOptions(SpaOptions copyFromOptions)
{ {
_defaultPage = copyFromOptions.DefaultPage; _defaultPage = copyFromOptions.DefaultPage;
DefaultPageFileProvider = copyFromOptions.DefaultPageFileProvider; DefaultPageStaticFileOptions = copyFromOptions.DefaultPageStaticFileOptions;
SourcePath = copyFromOptions.SourcePath; SourcePath = copyFromOptions.SourcePath;
} }
@@ -52,14 +53,14 @@ namespace Microsoft.AspNetCore.SpaServices
} }
/// <summary> /// <summary>
/// Gets or sets the <see cref="IFileProvider"/> that supplies content /// Gets or sets the <see cref="StaticFileOptions"/> that supplies content
/// for serving the SPA's default page. /// for serving the SPA's default page.
/// ///
/// If not set, a default file provider will read files from the /// If not set, a default file provider will read files from the
/// <see cref="IHostingEnvironment.WebRootPath"/>, which by default is /// <see cref="IHostingEnvironment.WebRootPath"/>, which by default is
/// the <c>wwwroot</c> directory. /// the <c>wwwroot</c> directory.
/// </summary> /// </summary>
public IFileProvider DefaultPageFileProvider { get; set; } public StaticFileOptions DefaultPageStaticFileOptions { get; set; }
/// <summary> /// <summary>
/// Gets or sets the path, relative to the application working directory, /// Gets or sets the path, relative to the application working directory,

View File

@@ -50,53 +50,75 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="applicationBuilder">The <see cref="IApplicationBuilder"/>.</param> /// <param name="applicationBuilder">The <see cref="IApplicationBuilder"/>.</param>
public static void UseSpaStaticFiles(this IApplicationBuilder applicationBuilder) public static void UseSpaStaticFiles(this IApplicationBuilder applicationBuilder)
{
UseSpaStaticFiles(applicationBuilder, new StaticFileOptions());
}
/// <summary>
/// Configures the application to serve static files for a Single Page Application (SPA).
/// The files will be located using the registered <see cref="ISpaStaticFileProvider"/> service.
/// </summary>
/// <param name="applicationBuilder">The <see cref="IApplicationBuilder"/>.</param>
/// <param name="options">Specifies options for serving the static files.</param>
public static void UseSpaStaticFiles(this IApplicationBuilder applicationBuilder, StaticFileOptions options)
{ {
if (applicationBuilder == null) if (applicationBuilder == null)
{ {
throw new ArgumentNullException(nameof(applicationBuilder)); throw new ArgumentNullException(nameof(applicationBuilder));
} }
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
UseSpaStaticFilesInternal(applicationBuilder, UseSpaStaticFilesInternal(applicationBuilder,
overrideFileProvider: null, staticFileOptions: options,
allowFallbackOnServingWebRootFiles: false); allowFallbackOnServingWebRootFiles: false);
} }
internal static void UseSpaStaticFilesInternal( internal static void UseSpaStaticFilesInternal(
this IApplicationBuilder app, this IApplicationBuilder app,
IFileProvider overrideFileProvider, StaticFileOptions staticFileOptions,
bool allowFallbackOnServingWebRootFiles) bool allowFallbackOnServingWebRootFiles)
{ {
var shouldServeStaticFiles = ShouldServeStaticFiles( if (staticFileOptions == null)
app,
overrideFileProvider,
allowFallbackOnServingWebRootFiles,
out var fileProviderOrDefault);
if (shouldServeStaticFiles)
{ {
app.UseStaticFiles(new StaticFileOptions throw new ArgumentNullException(nameof(staticFileOptions));
{
FileProvider = fileProviderOrDefault
});
} }
// If the file provider was explicitly supplied, that takes precedence over any other
// configured file provider. This is most useful if the application hosts multiple SPAs
// (via multiple calls to UseSpa()), so each needs to serve its own separate static files
// instead of using AddSpaStaticFiles/UseSpaStaticFiles.
// But if no file provider was specified, try to get one from the DI config.
if (staticFileOptions.FileProvider == null)
{
var shouldServeStaticFiles = ShouldServeStaticFiles(
app,
allowFallbackOnServingWebRootFiles,
out var fileProviderOrDefault);
if (shouldServeStaticFiles)
{
staticFileOptions.FileProvider = fileProviderOrDefault;
}
else
{
// The registered ISpaStaticFileProvider says we shouldn't
// serve static files
return;
}
}
app.UseStaticFiles(staticFileOptions);
} }
private static bool ShouldServeStaticFiles( private static bool ShouldServeStaticFiles(
IApplicationBuilder app, IApplicationBuilder app,
IFileProvider overrideFileProvider,
bool allowFallbackOnServingWebRootFiles, bool allowFallbackOnServingWebRootFiles,
out IFileProvider fileProviderOrDefault) out IFileProvider fileProviderOrDefault)
{ {
if (overrideFileProvider != null)
{
// If the file provider was explicitly supplied, that takes precedence over any other
// configured file provider. This is most useful if the application hosts multiple SPAs
// (via multiple calls to UseSpa()), so each needs to serve its own separate static files
// instead of using AddSpaStaticFiles/UseSpaStaticFiles.
fileProviderOrDefault = overrideFileProvider;
return true;
}
var spaStaticFilesService = app.ApplicationServices.GetService<ISpaStaticFileProvider>(); var spaStaticFilesService = app.ApplicationServices.GetService<ISpaStaticFileProvider>();
if (spaStaticFilesService != null) if (spaStaticFilesService != null)
{ {