Migrates more logic from the umb module over to netcore

This commit is contained in:
Shannon
2020-05-14 22:50:27 +10:00
parent 88f6d09ef9
commit 3d9603e669
5 changed files with 121 additions and 123 deletions

View File

@@ -27,8 +27,6 @@ namespace Umbraco.Extensions
return runtime.State.Level > RuntimeLevel.BootFailed;
}
/// <summary>
/// Start Umbraco
/// </summary>
@@ -38,27 +36,19 @@ namespace Umbraco.Extensions
{
if (app == null) throw new ArgumentNullException(nameof(app));
if (app.UmbracoCanBoot())
{
var runtime = app.ApplicationServices.GetRequiredService<IRuntime>();
var runtime = app.ApplicationServices.GetRequiredService<IRuntime>();
// Register a listener for application shutdown in order to terminate the runtime
var hostLifetime = app.ApplicationServices.GetRequiredService<IApplicationShutdownRegistry>();
var runtimeShutdown = new CoreRuntimeShutdown(runtime, hostLifetime);
hostLifetime.RegisterObject(runtimeShutdown);
// Register a listener for application shutdown in order to terminate the runtime
var hostLifetime = app.ApplicationServices.GetRequiredService<IApplicationShutdownRegistry>();
var runtimeShutdown = new CoreRuntimeShutdown(runtime, hostLifetime);
hostLifetime.RegisterObject(runtimeShutdown);
// Register our global threadabort enricher for logging
var threadAbortEnricher = app.ApplicationServices.GetRequiredService<ThreadAbortExceptionEnricher>();
LogContext.Push(threadAbortEnricher); // NOTE: We are not in a using clause because we are not removing it, it is on the global context
// Register our global threadabort enricher for logging
var threadAbortEnricher = app.ApplicationServices.GetRequiredService<ThreadAbortExceptionEnricher>();
LogContext.Push(threadAbortEnricher); // NOTE: We are not in a using clause because we are not removing it, it is on the global context
// Start the runtime!
runtime.Start();
}
else
{
// TODO: Register simple middleware to show the error like we used to in UmbracoModule? Or maybe that's part of a UseUmbracoWebsite/backoffice type thing .. probably :)
}
// Start the runtime!
runtime.Start();
return app;
}
@@ -73,15 +63,24 @@ namespace Umbraco.Extensions
{
if (app == null) throw new ArgumentNullException(nameof(app));
app.UseMiddleware<BootFailedMiddleware>();
if (!app.UmbracoCanBoot()) return app;
app.UseMiddleware<UmbracoRequestMiddleware>();
app.UseMiddleware<MiniProfilerMiddleware>();
if (!app.UmbracoCanBoot())
{
app.UseMiddleware<BootFailedMiddleware>();
}
else
{
app.UseMiddleware<UmbracoRequestMiddleware>();
app.UseMiddleware<MiniProfilerMiddleware>();
}
return app;
}
/// <summary>
/// Adds request based serilog enrichers to the LogContext for each request
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseUmbracoRequestLogging(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));

View File

@@ -92,6 +92,10 @@ namespace Umbraco.Web.Common.Install
return View();
}
/// <summary>
/// Used to perform the redirect to the installer when the runtime level is <see cref="RuntimeLevel.Install"/> or <see cref="RuntimeLevel.Upgrade"/>
/// </summary>
/// <returns></returns>
[HttpGet]
public ActionResult Redirect()
{

View File

@@ -8,6 +8,9 @@ using Umbraco.Core.Logging.Serilog.Enrichers;
namespace Umbraco.Web.Common.Middleware
{
/// <summary>
/// Adds request based serilog enrichers to the LogContext for each request
/// </summary>
public class UmbracoRequestLoggingMiddleware : IMiddleware
{
private readonly HttpSessionIdEnricher _sessionIdEnricher;

View File

@@ -6,6 +6,8 @@ using Umbraco.Web.Common.Lifetime;
using Umbraco.Core;
using Umbraco.Core.Logging;
using System.Threading;
using Umbraco.Core.Cache;
using System.Collections.Generic;
namespace Umbraco.Web.Common.Middleware
{
@@ -18,22 +20,26 @@ namespace Umbraco.Web.Common.Middleware
private readonly ILogger _logger;
private readonly IUmbracoRequestLifetimeManager _umbracoRequestLifetimeManager;
private readonly IUmbracoContextFactory _umbracoContextFactory;
private readonly IRequestCache _requestCache;
public UmbracoRequestMiddleware(
ILogger logger,
IUmbracoRequestLifetimeManager umbracoRequestLifetimeManager,
IUmbracoContextFactory umbracoContextFactory)
IUmbracoContextFactory umbracoContextFactory,
IRequestCache requestCache)
{
_logger = logger;
_umbracoRequestLifetimeManager = umbracoRequestLifetimeManager;
_umbracoContextFactory = umbracoContextFactory;
_requestCache = requestCache;
}
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
// do not process if client-side request
var requestUri = new Uri(context.Request.GetEncodedUrl(), UriKind.RelativeOrAbsolute);
if (new Uri(context.Request.GetEncodedUrl(), UriKind.RelativeOrAbsolute).IsClientSideRequest())
// do not process if client-side request
if (requestUri.IsClientSideRequest())
{
await next(context);
return;
@@ -43,6 +49,12 @@ namespace Umbraco.Web.Common.Middleware
try
{
if (umbracoContextReference.UmbracoContext.IsFrontEndUmbracoRequest)
{
LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId, _requestCache);
_logger.Verbose<UmbracoRequestMiddleware>("Begin request [{HttpRequestId}]: {RequestUrl}", httpRequestId, requestUri);
}
try
{
_umbracoRequestLifetimeManager.InitRequest(context);
@@ -52,15 +64,80 @@ namespace Umbraco.Web.Common.Middleware
// try catch so we don't kill everything in all requests
_logger.Error<UmbracoRequestMiddleware>(ex);
}
await next(context);
_umbracoRequestLifetimeManager.EndRequest(context);
finally
{
try
{
await next(context);
}
finally
{
_umbracoRequestLifetimeManager.EndRequest(context);
}
}
}
finally
{
umbracoContextReference.Dispose();
if (umbracoContextReference.UmbracoContext.IsFrontEndUmbracoRequest)
{
LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId, _requestCache);
_logger.Verbose<UmbracoRequestMiddleware>("End Request [{HttpRequestId}]: {RequestUrl} ({RequestDuration}ms)", httpRequestId, requestUri, DateTime.Now.Subtract(umbracoContextReference.UmbracoContext.ObjectCreated).TotalMilliseconds);
}
try
{
DisposeRequestCacheItems(_logger, _requestCache, requestUri);
}
finally
{
umbracoContextReference.Dispose();
}
}
}
/// <summary>
/// Any object that is in the HttpContext.Items collection that is IDisposable will get disposed on the end of the request
/// </summary>
/// <param name="http"></param>
/// <param name="requestCache"></param>
/// <param name="requestUri"></param>
private static void DisposeRequestCacheItems(ILogger logger, IRequestCache requestCache, Uri requestUri)
{
// do not process if client-side request
if (requestUri.IsClientSideRequest())
return;
//get a list of keys to dispose
var keys = new HashSet<string>();
foreach (var i in requestCache)
{
if (i.Value is IDisposeOnRequestEnd || i.Key is IDisposeOnRequestEnd)
{
keys.Add(i.Key);
}
}
//dispose each item and key that was found as disposable.
foreach (var k in keys)
{
try
{
requestCache.Get(k).DisposeIfDisposable();
}
catch (Exception ex)
{
logger.Error<UmbracoRequestMiddleware>("Could not dispose item with key " + k, ex);
}
try
{
k.DisposeIfDisposable();
}
catch (Exception ex)
{
logger.Error<UmbracoRequestMiddleware>("Could not dispose item key " + k, ex);
}
}
}
}
}

View File

@@ -210,11 +210,9 @@ namespace Umbraco.Web
case RuntimeLevel.Install:
case RuntimeLevel.Upgrade:
// redirect to install
ReportRuntime(level, "Umbraco must install or upgrade.");
var installPath = _uriUtility.ToAbsolute(Constants.SystemDirectories.Install);
var installUrl = $"{installPath}/?redir=true&url={HttpUtility.UrlEncode(uri.ToString())}";
httpContext.Response.Redirect(installUrl, true);
// NOTE: We have moved the logic that was here to netcore already
return false; // cannot serve content
default:
@@ -222,17 +220,6 @@ namespace Umbraco.Web
}
}
private static bool _reported;
private static RuntimeLevel _reportedLevel;
private void ReportRuntime(RuntimeLevel level, string message)
{
if (_reported && _reportedLevel == level) return;
_reported = true;
_reportedLevel = level;
_logger.Warn<UmbracoModule>(message);
}
// ensures Umbraco has at least one published node
// if not, rewrites to splash and return false
// if yes, return true
@@ -309,47 +296,7 @@ namespace Umbraco.Web
}
/// <summary>
/// Any object that is in the HttpContext.Items collection that is IDisposable will get disposed on the end of the request
/// </summary>
/// <param name="http"></param>
private void DisposeRequestCacheItems(HttpContext http, IRequestCache requestCache)
{
// do not process if client-side request
if (http.Request.Url.IsClientSideRequest())
return;
//get a list of keys to dispose
var keys = new HashSet<string>();
foreach (var i in requestCache)
{
if (i.Value is IDisposeOnRequestEnd || i.Key is IDisposeOnRequestEnd)
{
keys.Add(i.Key);
}
}
//dispose each item and key that was found as disposable.
foreach (var k in keys)
{
try
{
requestCache.Get(k).DisposeIfDisposable();
}
catch (Exception ex)
{
_logger.Error<UmbracoModule>("Could not dispose item with key " + k, ex);
}
try
{
k.DisposeIfDisposable();
}
catch (Exception ex)
{
_logger.Error<UmbracoModule>("Could not dispose item key " + k, ex);
}
}
}
#endregion
#region IHttpModule
@@ -365,32 +312,9 @@ namespace Umbraco.Web
{
var httpContext = ((HttpApplication) sender).Context;
LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId, _requestCache);
_logger.Verbose<UmbracoModule>("Begin request [{HttpRequestId}]: {RequestUrl}", httpRequestId, httpContext.Request.Url);
BeginRequest(new HttpContextWrapper(httpContext));
};
//disable asp.net headers (security)
// This is the correct place to modify headers according to MS:
// https://our.umbraco.com/forum/umbraco-7/using-umbraco-7/65241-Heap-error-from-header-manipulation?p=0#comment220889
app.PostReleaseRequestState += (sender, args) =>
{
var httpContext = ((HttpApplication) sender).Context;
try
{
httpContext.Response.Headers.Remove("Server");
//this doesn't normally work since IIS sets it but we'll keep it here anyways.
httpContext.Response.Headers.Remove("X-Powered-By");
httpContext.Response.Headers.Remove("X-AspNet-Version");
httpContext.Response.Headers.Remove("X-AspNetMvc-Version");
}
catch (PlatformNotSupportedException)
{
// can't remove headers this way on IIS6 or cassini.
}
};
app.PostAuthenticateRequest += (sender, e) =>
{
var httpContext = ((HttpApplication) sender).Context;
@@ -408,16 +332,7 @@ namespace Umbraco.Web
{
var httpContext = ((HttpApplication) sender).Context;
if (Current.UmbracoContext != null && Current.UmbracoContext.IsFrontEndUmbracoRequest)
{
LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId, _requestCache);
_logger.Verbose<UmbracoModule>("End Request [{HttpRequestId}]: {RequestUrl} ({RequestDuration}ms)", httpRequestId, httpContext.Request.Url, DateTime.Now.Subtract(Current.UmbracoContext.ObjectCreated).TotalMilliseconds);
}
UmbracoModule.OnEndRequest(this, new UmbracoRequestEventArgs(Current.UmbracoContext));
DisposeRequestCacheItems(httpContext, _requestCache);
};
}