|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.StaticAssets;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Microsoft.AspNetCore.Builder;
/// <summary>
/// Contains methods to integrate static assets with endpoints.
/// </summary>
public static class StaticAssetsEndpointRouteBuilderExtensions
{
/// <summary>
/// Maps static files produced during the build as endpoints.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/>.</param>
/// <param name="staticAssetsManifestPath">The path to the static assets manifest file.</param>
/// <remarks>
/// The <paramref name="staticAssetsManifestPath"/> can be <see langword="null"/> to use the <see cref="IHostEnvironment.ApplicationName"/> to locate the manifest.
/// As an alternative, a full path can be specified to the manifest file. If a relative path is used, we'll search for the file in the <see cref="AppContext.BaseDirectory"/>.
/// </remarks>
public static StaticAssetsEndpointConventionBuilder MapStaticAssets(this IEndpointRouteBuilder endpoints, string? staticAssetsManifestPath = null)
{
ArgumentNullException.ThrowIfNull(endpoints);
var environment = endpoints.ServiceProvider.GetRequiredService<IWebHostEnvironment>();
staticAssetsManifestPath ??= $"{environment.ApplicationName}.staticwebassets.endpoints.json";
staticAssetsManifestPath = !Path.IsPathRooted(staticAssetsManifestPath) ?
Path.Combine(AppContext.BaseDirectory, staticAssetsManifestPath) :
staticAssetsManifestPath;
var result = MapStaticAssetsCore(endpoints, staticAssetsManifestPath);
if (StaticAssetDevelopmentRuntimeHandler.IsEnabled(result.IsBuildManifest, endpoints.ServiceProvider))
{
StaticAssetDevelopmentRuntimeHandler.EnableSupport(endpoints, result, environment, result.Descriptors);
}
return result;
}
private static StaticAssetsEndpointConventionBuilder MapStaticAssetsCore(
IEndpointRouteBuilder endpoints,
string manifestPath)
{
var builder = GetExistingBuilder(endpoints, manifestPath);
if (builder != null)
{
return builder;
}
var manifest = ResolveManifest(manifestPath);
var dataSource = StaticAssetsManifest.CreateDataSource(endpoints, manifestPath, manifest.Endpoints, manifest.IsBuildManifest());
return dataSource.DefaultBuilder;
}
private static StaticAssetsManifest ResolveManifest(string manifestPath)
{
if (!File.Exists(manifestPath))
{
throw new InvalidOperationException($"The static resources manifest file '{manifestPath}' was not found.");
}
return StaticAssetsManifest.Parse(manifestPath);
}
private static StaticAssetsEndpointConventionBuilder? GetExistingBuilder(IEndpointRouteBuilder endpoints, string manifestPath)
{
foreach (var ds in endpoints.DataSources)
{
if (ds is StaticAssetsEndpointDataSource sads && sads.ManifestPath.Equals(manifestPath, StringComparison.Ordinal))
{
return sads.DefaultBuilder;
}
}
return null;
}
// For testing purposes
internal static StaticAssetsEndpointConventionBuilder MapStaticAssets(this IEndpointRouteBuilder endpoints, StaticAssetsManifest manifest)
{
ArgumentNullException.ThrowIfNull(endpoints);
var environment = endpoints.ServiceProvider.GetRequiredService<IWebHostEnvironment>();
var result = StaticAssetsManifest.CreateDataSource(endpoints, "", manifest.Endpoints, manifest.IsBuildManifest()).DefaultBuilder;
if (StaticAssetDevelopmentRuntimeHandler.IsEnabled(result.IsBuildManifest, endpoints.ServiceProvider))
{
StaticAssetDevelopmentRuntimeHandler.EnableSupport(endpoints, result, environment, result.Descriptors);
}
return result;
}
}
|