2018-07-06 18:37:07 +02:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Web;
|
|
|
|
|
|
using System.Web.Routing;
|
|
|
|
|
|
using Umbraco.Core;
|
|
|
|
|
|
using Umbraco.Core.Configuration;
|
|
|
|
|
|
using Umbraco.Core.IO;
|
|
|
|
|
|
using Umbraco.Core.Logging;
|
|
|
|
|
|
using Umbraco.Web.Routing;
|
|
|
|
|
|
using Umbraco.Core.Exceptions;
|
|
|
|
|
|
using Umbraco.Core.Security;
|
|
|
|
|
|
using Umbraco.Web.Composing;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Umbraco.Web
|
|
|
|
|
|
{
|
|
|
|
|
|
// notes
|
|
|
|
|
|
//
|
|
|
|
|
|
// also look at IOHelper.ResolveUrlsFromTextString - nightmarish?!
|
|
|
|
|
|
//
|
|
|
|
|
|
// context.RewritePath supports ~/ or else must begin with /vdir
|
|
|
|
|
|
// Request.RawUrl is still there
|
|
|
|
|
|
// response.Redirect does?! always remap to /vdir?!
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Represents the main Umbraco module.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <remarks>
|
|
|
|
|
|
/// <para>Is registered by the <see cref="Umbraco.Web.Runtime.WebRuntime"/>.</para>
|
|
|
|
|
|
/// <para>Do *not* try to use that one as a module in web.config.</para>
|
|
|
|
|
|
/// </remarks>
|
|
|
|
|
|
public class UmbracoInjectedModule : IHttpModule
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly IGlobalSettings _globalSettings;
|
|
|
|
|
|
private readonly IRuntimeState _runtime;
|
|
|
|
|
|
private readonly ILogger _logger;
|
2019-01-31 09:08:51 +01:00
|
|
|
|
private readonly IPublishedRouter _publishedRouter;
|
2019-02-14 12:11:06 +01:00
|
|
|
|
private readonly IUmbracoContextFactory _umbracoContextFactory;
|
2019-09-10 14:23:42 +10:00
|
|
|
|
private readonly RoutableDocumentFilter _routableDocumentLookup;
|
2018-07-06 18:37:07 +02:00
|
|
|
|
|
|
|
|
|
|
public UmbracoInjectedModule(
|
|
|
|
|
|
IGlobalSettings globalSettings,
|
|
|
|
|
|
IRuntimeState runtime,
|
|
|
|
|
|
ILogger logger,
|
2019-01-31 09:08:51 +01:00
|
|
|
|
IPublishedRouter publishedRouter,
|
2019-09-09 23:25:28 +10:00
|
|
|
|
IUmbracoContextFactory umbracoContextFactory,
|
2019-09-10 14:23:42 +10:00
|
|
|
|
RoutableDocumentFilter routableDocumentLookup)
|
2018-07-06 18:37:07 +02:00
|
|
|
|
{
|
|
|
|
|
|
_globalSettings = globalSettings;
|
|
|
|
|
|
_runtime = runtime;
|
|
|
|
|
|
_logger = logger;
|
|
|
|
|
|
_publishedRouter = publishedRouter;
|
2019-02-14 12:11:06 +01:00
|
|
|
|
_umbracoContextFactory = umbracoContextFactory;
|
2019-09-10 14:10:26 +10:00
|
|
|
|
_routableDocumentLookup = routableDocumentLookup;
|
2018-07-06 18:37:07 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#region HttpModule event handlers
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Begins to process a request.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="httpContext"></param>
|
|
|
|
|
|
private void BeginRequest(HttpContextBase httpContext)
|
|
|
|
|
|
{
|
|
|
|
|
|
// ensure application url is initialized
|
|
|
|
|
|
((RuntimeState) Current.RuntimeState).EnsureApplicationUrl(httpContext.Request);
|
|
|
|
|
|
|
|
|
|
|
|
// do not process if client-side request
|
|
|
|
|
|
if (httpContext.Request.Url.IsClientSideRequest())
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// write the trace output for diagnostics at the end of the request
|
|
|
|
|
|
httpContext.Trace.Write("UmbracoModule", "Umbraco request begins");
|
|
|
|
|
|
|
|
|
|
|
|
// ok, process
|
|
|
|
|
|
|
2019-02-15 10:31:45 +01:00
|
|
|
|
// TODO: should we move this to after we've ensured we are processing a routable page?
|
2019-02-14 12:11:06 +01:00
|
|
|
|
// ensure there's an UmbracoContext registered for the current request
|
|
|
|
|
|
// registers the context reference so its disposed at end of request
|
|
|
|
|
|
var umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext(httpContext);
|
|
|
|
|
|
httpContext.DisposeOnPipelineCompleted(umbracoContextReference);
|
2018-07-06 18:37:07 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2019-01-26 10:52:19 -05:00
|
|
|
|
/// Processes the Umbraco Request
|
2018-07-06 18:37:07 +02:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="httpContext"></param>
|
|
|
|
|
|
/// <remarks>
|
|
|
|
|
|
///
|
|
|
|
|
|
/// This will check if we are trying to route to the default back office page (i.e. ~/Umbraco/ or ~/Umbraco or ~/Umbraco/Default )
|
|
|
|
|
|
/// and ensure that the MVC handler executes for that. This is required because the route for /Umbraco will never execute because
|
|
|
|
|
|
/// files/folders exist there and we cannot set the RouteCollection.RouteExistingFiles = true since that will muck a lot of other things up.
|
|
|
|
|
|
/// So we handle it here and explicitly execute the MVC controller.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// </remarks>
|
|
|
|
|
|
void ProcessRequest(HttpContextBase httpContext)
|
|
|
|
|
|
{
|
|
|
|
|
|
// do not process if client-side request
|
|
|
|
|
|
if (httpContext.Request.Url.IsClientSideRequest())
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2019-02-14 09:49:45 +01:00
|
|
|
|
if (Current.UmbracoContext == null)
|
|
|
|
|
|
throw new InvalidOperationException("The Current.UmbracoContext is null, ProcessRequest cannot proceed unless there is a current UmbracoContext");
|
2018-07-06 18:37:07 +02:00
|
|
|
|
|
2019-02-14 09:49:45 +01:00
|
|
|
|
var umbracoContext = Current.UmbracoContext;
|
2018-07-06 18:37:07 +02:00
|
|
|
|
|
|
|
|
|
|
// re-write for the default back office path
|
|
|
|
|
|
if (httpContext.Request.Url.IsDefaultBackOfficeRequest(_globalSettings))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (EnsureRuntime(httpContext, umbracoContext.OriginalRequestUrl))
|
|
|
|
|
|
RewriteToBackOfficeHandler(httpContext);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// do not process if this request is not a front-end routable page
|
|
|
|
|
|
var isRoutableAttempt = EnsureUmbracoRoutablePage(umbracoContext, httpContext);
|
|
|
|
|
|
|
|
|
|
|
|
// raise event here
|
|
|
|
|
|
UmbracoModule.OnRouteAttempt(this, new RoutableAttemptEventArgs(isRoutableAttempt.Result, umbracoContext, httpContext));
|
|
|
|
|
|
if (isRoutableAttempt.Success == false) return;
|
|
|
|
|
|
|
|
|
|
|
|
httpContext.Trace.Write("UmbracoModule", "Umbraco request confirmed");
|
|
|
|
|
|
|
|
|
|
|
|
// ok, process
|
|
|
|
|
|
|
|
|
|
|
|
// note: requestModule.UmbracoRewrite also did some stripping of &umbPage
|
|
|
|
|
|
// from the querystring... that was in v3.x to fix some issues with pre-forms
|
2019-01-26 10:52:19 -05:00
|
|
|
|
// auth. Paul Sterling confirmed in Jan. 2013 that we can get rid of it.
|
2018-07-06 18:37:07 +02:00
|
|
|
|
|
2019-01-26 10:52:19 -05:00
|
|
|
|
// instantiate, prepare and process the published content request
|
2018-07-06 18:37:07 +02:00
|
|
|
|
// important to use CleanedUmbracoUrl - lowercase path-only version of the current url
|
|
|
|
|
|
var request = _publishedRouter.CreateRequest(umbracoContext);
|
|
|
|
|
|
umbracoContext.PublishedRequest = request;
|
|
|
|
|
|
_publishedRouter.PrepareRequest(request);
|
|
|
|
|
|
|
|
|
|
|
|
// HandleHttpResponseStatus returns a value indicating that the request should
|
|
|
|
|
|
// not be processed any further, eg because it has been redirect. then, exit.
|
|
|
|
|
|
if (UmbracoModule.HandleHttpResponseStatus(httpContext, request, _logger))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (request.HasPublishedContent == false)
|
|
|
|
|
|
httpContext.RemapHandler(new PublishedContentNotFoundHandler());
|
|
|
|
|
|
else
|
|
|
|
|
|
RewriteToUmbracoHandler(httpContext, request);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Methods
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Checks the current request and ensures that it is routable based on the structure of the request and URI
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="context"></param>
|
|
|
|
|
|
/// <param name="httpContext"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
internal Attempt<EnsureRoutableOutcome> EnsureUmbracoRoutablePage(UmbracoContext context, HttpContextBase httpContext)
|
|
|
|
|
|
{
|
|
|
|
|
|
var uri = context.OriginalRequestUrl;
|
|
|
|
|
|
|
|
|
|
|
|
var reason = EnsureRoutableOutcome.IsRoutable;
|
|
|
|
|
|
|
|
|
|
|
|
// ensure this is a document request
|
2019-09-16 17:55:04 +10:00
|
|
|
|
if (!_routableDocumentLookup.IsDocumentRequest(httpContext, context.OriginalRequestUrl))
|
2018-07-06 18:37:07 +02:00
|
|
|
|
{
|
|
|
|
|
|
reason = EnsureRoutableOutcome.NotDocumentRequest;
|
|
|
|
|
|
}
|
|
|
|
|
|
// ensure the runtime is in the proper state
|
|
|
|
|
|
// and deal with needed redirects, etc
|
2019-09-10 14:10:26 +10:00
|
|
|
|
else if (!EnsureRuntime(httpContext, uri))
|
2018-07-06 18:37:07 +02:00
|
|
|
|
{
|
|
|
|
|
|
reason = EnsureRoutableOutcome.NotReady;
|
|
|
|
|
|
}
|
|
|
|
|
|
// ensure Umbraco has documents to serve
|
2019-09-10 14:10:26 +10:00
|
|
|
|
else if (!EnsureHasContent(context, httpContext))
|
2018-07-06 18:37:07 +02:00
|
|
|
|
{
|
|
|
|
|
|
reason = EnsureRoutableOutcome.NoContent;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return Attempt.If(reason == EnsureRoutableOutcome.IsRoutable, reason);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-11-12 15:25:21 +01:00
|
|
|
|
|
2018-07-06 18:37:07 +02:00
|
|
|
|
|
|
|
|
|
|
private bool EnsureRuntime(HttpContextBase httpContext, Uri uri)
|
|
|
|
|
|
{
|
|
|
|
|
|
var level = _runtime.Level;
|
|
|
|
|
|
switch (level)
|
|
|
|
|
|
{
|
2019-01-30 08:35:19 +01:00
|
|
|
|
// we should never handle Unknown nor Boot: the runtime boots in Application_Start
|
|
|
|
|
|
// and as long as it has not booted, no request other than the initial request is
|
|
|
|
|
|
// going to be served (see https://stackoverflow.com/a/21402100)
|
|
|
|
|
|
// we should never handle BootFailed: if boot failed, the pipeline should not run
|
|
|
|
|
|
// at all
|
2018-07-06 18:37:07 +02:00
|
|
|
|
case RuntimeLevel.Unknown:
|
|
|
|
|
|
case RuntimeLevel.Boot:
|
|
|
|
|
|
case RuntimeLevel.BootFailed:
|
2019-08-16 16:18:58 +10:00
|
|
|
|
throw new PanicException($"Unexpected runtime level: {level}.");
|
2018-07-06 18:37:07 +02:00
|
|
|
|
|
|
|
|
|
|
case RuntimeLevel.Run:
|
|
|
|
|
|
// ok
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
case RuntimeLevel.Install:
|
|
|
|
|
|
case RuntimeLevel.Upgrade:
|
|
|
|
|
|
// redirect to install
|
|
|
|
|
|
ReportRuntime(level, "Umbraco must install or upgrade.");
|
2019-11-12 15:25:21 +01:00
|
|
|
|
var installPath = UriUtility.ToAbsolute(Current.SystemDirectories.Install);
|
2018-07-06 18:37:07 +02:00
|
|
|
|
var installUrl = $"{installPath}/?redir=true&url={HttpUtility.UrlEncode(uri.ToString())}";
|
|
|
|
|
|
httpContext.Response.Redirect(installUrl, true);
|
|
|
|
|
|
return false; // cannot serve content
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
2019-01-30 08:35:19 +01:00
|
|
|
|
throw new NotSupportedException($"Unexpected runtime level: {level}.");
|
2018-07-06 18:37:07 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
private bool EnsureHasContent(UmbracoContext context, HttpContextBase httpContext)
|
|
|
|
|
|
{
|
2019-04-22 18:14:03 +02:00
|
|
|
|
if (context.Content.HasContent())
|
2018-07-06 18:37:07 +02:00
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
_logger.Warn<UmbracoModule>("Umbraco has no content");
|
|
|
|
|
|
|
|
|
|
|
|
const string noContentUrl = "~/config/splashes/noNodes.aspx";
|
|
|
|
|
|
httpContext.RewritePath(UriUtility.ToAbsolute(noContentUrl));
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Rewrites to the default back office page.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="context"></param>
|
|
|
|
|
|
private void RewriteToBackOfficeHandler(HttpContextBase context)
|
|
|
|
|
|
{
|
|
|
|
|
|
// GlobalSettings.Path has already been through IOHelper.ResolveUrl() so it begins with / and vdir (if any)
|
|
|
|
|
|
var rewritePath = _globalSettings.Path.TrimEnd('/') + "/Default";
|
|
|
|
|
|
// rewrite the path to the path of the handler (i.e. /umbraco/RenderMvc)
|
|
|
|
|
|
context.RewritePath(rewritePath, "", "", false);
|
|
|
|
|
|
|
|
|
|
|
|
//if it is MVC we need to do something special, we are not using TransferRequest as this will
|
2019-01-26 10:52:19 -05:00
|
|
|
|
//require us to rewrite the path with query strings and then re-parse the query strings, this would
|
2018-07-06 18:37:07 +02:00
|
|
|
|
//also mean that we need to handle IIS 7 vs pre-IIS 7 differently. Instead we are just going to create
|
|
|
|
|
|
//an instance of the UrlRoutingModule and call it's PostResolveRequestCache method. This does:
|
|
|
|
|
|
// * Looks up the route based on the new rewritten URL
|
|
|
|
|
|
// * Creates the RequestContext with all route parameters and then executes the correct handler that matches the route
|
|
|
|
|
|
//we also cannot re-create this functionality because the setter for the HttpContext.Request.RequestContext is internal
|
|
|
|
|
|
//so really, this is pretty much the only way without using Server.TransferRequest and if we did that, we'd have to rethink
|
|
|
|
|
|
//a bunch of things!
|
|
|
|
|
|
var urlRouting = new UrlRoutingModule();
|
|
|
|
|
|
urlRouting.PostResolveRequestCache(context);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Rewrites to the Umbraco handler - we always send the request via our MVC rendering engine, this will deal with
|
|
|
|
|
|
/// requests destined for webforms.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="context"></param>
|
|
|
|
|
|
/// <param name="pcr"> </param>
|
|
|
|
|
|
private void RewriteToUmbracoHandler(HttpContextBase context, PublishedRequest pcr)
|
|
|
|
|
|
{
|
|
|
|
|
|
// NOTE: we do not want to use TransferRequest even though many docs say it is better with IIS7, turns out this is
|
|
|
|
|
|
// not what we need. The purpose of TransferRequest is to ensure that .net processes all of the rules for the newly
|
|
|
|
|
|
// rewritten url, but this is not what we want!
|
|
|
|
|
|
// read: http://forums.iis.net/t/1146511.aspx
|
|
|
|
|
|
|
|
|
|
|
|
var query = pcr.Uri.Query.TrimStart('?');
|
|
|
|
|
|
|
|
|
|
|
|
// GlobalSettings.Path has already been through IOHelper.ResolveUrl() so it begins with / and vdir (if any)
|
|
|
|
|
|
var rewritePath = _globalSettings.Path.TrimEnd('/') + "/RenderMvc";
|
|
|
|
|
|
// rewrite the path to the path of the handler (i.e. /umbraco/RenderMvc)
|
|
|
|
|
|
context.RewritePath(rewritePath, "", query, false);
|
|
|
|
|
|
|
|
|
|
|
|
//if it is MVC we need to do something special, we are not using TransferRequest as this will
|
2019-01-26 10:52:19 -05:00
|
|
|
|
//require us to rewrite the path with query strings and then re-parse the query strings, this would
|
2018-07-06 18:37:07 +02:00
|
|
|
|
//also mean that we need to handle IIS 7 vs pre-IIS 7 differently. Instead we are just going to create
|
|
|
|
|
|
//an instance of the UrlRoutingModule and call it's PostResolveRequestCache method. This does:
|
|
|
|
|
|
// * Looks up the route based on the new rewritten URL
|
|
|
|
|
|
// * Creates the RequestContext with all route parameters and then executes the correct handler that matches the route
|
|
|
|
|
|
//we also cannot re-create this functionality because the setter for the HttpContext.Request.RequestContext is internal
|
|
|
|
|
|
//so really, this is pretty much the only way without using Server.TransferRequest and if we did that, we'd have to rethink
|
|
|
|
|
|
//a bunch of things!
|
|
|
|
|
|
var urlRouting = new UrlRoutingModule();
|
|
|
|
|
|
urlRouting.PostResolveRequestCache(context);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <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 DisposeHttpContextItems(HttpContext http)
|
|
|
|
|
|
{
|
|
|
|
|
|
// do not process if client-side request
|
|
|
|
|
|
if (http.Request.Url.IsClientSideRequest())
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
//get a list of keys to dispose
|
|
|
|
|
|
var keys = new HashSet<object>();
|
|
|
|
|
|
foreach (DictionaryEntry i in http.Items)
|
|
|
|
|
|
{
|
|
|
|
|
|
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
|
|
|
|
|
|
{
|
|
|
|
|
|
http.Items[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
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Initialize the module, this will trigger for each new application
|
|
|
|
|
|
/// and there may be more than 1 application per application domain
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="app"></param>
|
|
|
|
|
|
public void Init(HttpApplication app)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_runtime.Level == RuntimeLevel.BootFailed)
|
|
|
|
|
|
{
|
|
|
|
|
|
// there's nothing we can do really
|
|
|
|
|
|
app.BeginRequest += (sender, args) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
// would love to avoid throwing, and instead display a customized Umbraco 500
|
|
|
|
|
|
// page - however if we don't throw here, something else might go wrong, and
|
|
|
|
|
|
// it's this later exception that would be reported. could not figure out how
|
|
|
|
|
|
// to prevent it, either with httpContext.Response.End() or .ApplicationInstance
|
|
|
|
|
|
// .CompleteRequest()
|
|
|
|
|
|
|
|
|
|
|
|
// also, if something goes wrong with our DI setup, the logging subsystem may
|
|
|
|
|
|
// not even kick in, so here we try to give as much detail as possible
|
|
|
|
|
|
|
2018-10-25 15:07:04 +02:00
|
|
|
|
BootFailedException.Rethrow(Core.Composing.Current.RuntimeState.BootFailedException);
|
2018-07-06 18:37:07 +02:00
|
|
|
|
};
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
app.BeginRequest += (sender, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var httpContext = ((HttpApplication) sender).Context;
|
2018-10-08 19:22:20 +02:00
|
|
|
|
|
|
|
|
|
|
LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId);
|
|
|
|
|
|
|
|
|
|
|
|
_logger.Verbose<UmbracoModule>("Begin request [{HttpRequestId}]: {RequestUrl}", httpRequestId, httpContext.Request.Url);
|
2018-07-06 18:37:07 +02:00
|
|
|
|
BeginRequest(new HttpContextWrapper(httpContext));
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//disable asp.net headers (security)
|
|
|
|
|
|
// This is the correct place to modify headers according to MS:
|
2018-07-31 14:51:56 +02:00
|
|
|
|
// https://our.umbraco.com/forum/umbraco-7/using-umbraco-7/65241-Heap-error-from-header-manipulation?p=0#comment220889
|
2018-07-06 18:37:07 +02:00
|
|
|
|
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;
|
|
|
|
|
|
//ensure the thread culture is set
|
|
|
|
|
|
httpContext.User?.Identity?.EnsureCulture();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
app.PostResolveRequestCache += (sender, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var httpContext = ((HttpApplication) sender).Context;
|
|
|
|
|
|
ProcessRequest(new HttpContextWrapper(httpContext));
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
app.EndRequest += (sender, args) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var httpContext = ((HttpApplication) sender).Context;
|
|
|
|
|
|
|
2019-02-14 09:49:45 +01:00
|
|
|
|
if (Current.UmbracoContext != null && Current.UmbracoContext.IsFrontEndUmbracoRequest)
|
2018-07-06 18:37:07 +02:00
|
|
|
|
{
|
2018-10-08 19:22:20 +02:00
|
|
|
|
LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId);
|
|
|
|
|
|
|
2019-02-14 09:49:45 +01:00
|
|
|
|
_logger.Verbose<UmbracoModule>("End Request [{HttpRequestId}]: {RequestUrl} ({RequestDuration}ms)", httpRequestId, httpContext.Request.Url, DateTime.Now.Subtract(Current.UmbracoContext.ObjectCreated).TotalMilliseconds);
|
2018-07-06 18:37:07 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-02-14 09:49:45 +01:00
|
|
|
|
UmbracoModule.OnEndRequest(this, new UmbracoRequestEventArgs(Current.UmbracoContext, new HttpContextWrapper(httpContext)));
|
2018-07-06 18:37:07 +02:00
|
|
|
|
|
|
|
|
|
|
DisposeHttpContextItems(httpContext);
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2019-11-12 15:25:21 +01:00
|
|
|
|
|
2018-07-06 18:37:07 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|