File: StaticAssetsEndpointRouteBuilderExtensions.cs
Web Access
Project: src\src\StaticAssets\src\Microsoft.AspNetCore.StaticAssets.csproj (Microsoft.AspNetCore.StaticAssets)
// 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;
    }
}