using System; using System.IO; using Dazinator.Extensions.FileProviders.PrependBasePath; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Serilog.Context; using StackExchange.Profiling; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Logging.Serilog.Enrichers; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Web.Common.ApplicationBuilder; using Umbraco.Cms.Web.Common.Middleware; using Umbraco.Cms.Web.Common.Plugins; using IHostingEnvironment = Umbraco.Cms.Core.Hosting.IHostingEnvironment; namespace Umbraco.Extensions { /// /// extensions for Umbraco /// public static class ApplicationBuilderExtensions { /// /// Configures and use services required for using Umbraco /// public static IUmbracoApplicationBuilder UseUmbraco(this IApplicationBuilder app) => new UmbracoApplicationBuilder(app); /// /// Returns true if Umbraco is greater than /// public static bool UmbracoCanBoot(this IApplicationBuilder app) => app.ApplicationServices.GetRequiredService().UmbracoCanBoot(); /// /// Enables core Umbraco functionality /// public static IApplicationBuilder UseUmbracoCore(this IApplicationBuilder app) { if (app == null) { throw new ArgumentNullException(nameof(app)); } if (!app.UmbracoCanBoot()) { return app; } // Register our global threadabort enricher for logging ThreadAbortExceptionEnricher threadAbortEnricher = app.ApplicationServices.GetRequiredService(); LogContext.Push(threadAbortEnricher); // NOTE: We are not in a using clause because we are not removing it, it is on the global context return app; } /// /// Enables middlewares required to run Umbraco /// /// /// Must occur before UseRouting /// public static IApplicationBuilder UseUmbracoRouting(this IApplicationBuilder app) { // TODO: This method could be internal or part of another call - this is a required system so should't be 'opt-in' if (app == null) { throw new ArgumentNullException(nameof(app)); } if (!app.UmbracoCanBoot()) { app.UseStaticFiles(); // We need static files to show the nice error page. app.UseMiddleware(); } else { app.UseMiddleware(); app.UseMiddleware(); app.UseMiddleware(); } return app; } /// /// Adds request based serilog enrichers to the LogContext for each request /// public static IApplicationBuilder UseUmbracoRequestLogging(this IApplicationBuilder app) { if (app == null) { throw new ArgumentNullException(nameof(app)); } if (!app.UmbracoCanBoot()) return app; app.UseMiddleware(); return app; } /// /// Allow static file access for App_Plugins folders /// /// /// public static IApplicationBuilder UseUmbracoPluginsStaticFiles(this IApplicationBuilder app) { var hostingEnvironment = app.ApplicationServices.GetRequiredService(); var pluginFolder = hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins); if (Directory.Exists(pluginFolder)) { var umbracoPluginSettings = app.ApplicationServices.GetRequiredService>(); var pluginFileProvider = new UmbracoPluginPhysicalFileProvider( pluginFolder, umbracoPluginSettings); IWebHostEnvironment? webHostEnvironment = app.ApplicationServices.GetService(); if (webHostEnvironment is not null) { webHostEnvironment.WebRootFileProvider = webHostEnvironment.WebRootFileProvider.ConcatComposite(new PrependBasePathFileProvider(Constants.SystemDirectories.AppPlugins, pluginFileProvider)); } } return app; } } }