less allocations with AbsolutePathDecoded. removes more aspx checks, adds UmbracoRouteValueTransformerTests, adds interface for IRoutableDocumentFilter
This commit is contained in:
@@ -49,7 +49,7 @@ namespace Umbraco.Web.Routing
|
||||
}
|
||||
|
||||
IPublishedContent node = null;
|
||||
var path = frequest.Uri.GetAbsolutePathDecoded();
|
||||
var path = frequest.AbsolutePathDecoded;
|
||||
|
||||
var nodeId = -1;
|
||||
|
||||
|
||||
@@ -51,8 +51,8 @@ namespace Umbraco.Web.Routing
|
||||
}
|
||||
|
||||
var route = frequest.Domain != null
|
||||
? frequest.Domain.ContentId + DomainUtilities.PathRelativeToDomain(frequest.Domain.Uri, frequest.Uri.GetAbsolutePathDecoded())
|
||||
: frequest.Uri.GetAbsolutePathDecoded();
|
||||
? frequest.Domain.ContentId + DomainUtilities.PathRelativeToDomain(frequest.Domain.Uri, frequest.AbsolutePathDecoded)
|
||||
: frequest.AbsolutePathDecoded;
|
||||
|
||||
IRedirectUrl redirectUrl = _redirectUrlService.GetMostRecentRedirectUrl(route, frequest.Culture);
|
||||
|
||||
|
||||
@@ -44,11 +44,11 @@ namespace Umbraco.Web.Routing
|
||||
string route;
|
||||
if (frequest.Domain != null)
|
||||
{
|
||||
route = frequest.Domain.ContentId + DomainUtilities.PathRelativeToDomain(frequest.Domain.Uri, frequest.Uri.GetAbsolutePathDecoded());
|
||||
route = frequest.Domain.ContentId + DomainUtilities.PathRelativeToDomain(frequest.Domain.Uri, frequest.AbsolutePathDecoded);
|
||||
}
|
||||
else
|
||||
{
|
||||
route = frequest.Uri.GetAbsolutePathDecoded();
|
||||
route = frequest.AbsolutePathDecoded;
|
||||
}
|
||||
|
||||
IPublishedContent node = FindContent(frequest, route);
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Umbraco.Web.Routing
|
||||
umbCtx.Content,
|
||||
frequest.Domain != null ? frequest.Domain.ContentId : 0,
|
||||
frequest.Culture,
|
||||
frequest.Uri.GetAbsolutePathDecoded());
|
||||
frequest.AbsolutePathDecoded);
|
||||
|
||||
if (node != null)
|
||||
{
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Umbraco.Web.Routing
|
||||
/// <remarks>If successful, also assigns the template.</remarks>
|
||||
public override bool TryFindContent(IPublishedRequestBuilder frequest)
|
||||
{
|
||||
var path = frequest.Uri.GetAbsolutePathDecoded();
|
||||
var path = frequest.AbsolutePathDecoded;
|
||||
|
||||
if (frequest.Domain != null)
|
||||
{
|
||||
|
||||
@@ -364,9 +364,7 @@ namespace Umbraco.Web.Routing
|
||||
/// <returns>The path part relative to the uri of the domain.</returns>
|
||||
/// <remarks>Eg the relative part of <c>/foo/bar/nil</c> to domain <c>example.com/foo</c> is <c>/bar/nil</c>.</remarks>
|
||||
public static string PathRelativeToDomain(Uri domainUri, string path)
|
||||
{
|
||||
return path.Substring(domainUri.GetAbsolutePathDecoded().Length).EnsureStartsWith('/');
|
||||
}
|
||||
=> path.Substring(domainUri.GetAbsolutePathDecoded().Length).EnsureStartsWith('/');
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -18,6 +18,11 @@ namespace Umbraco.Web.Routing
|
||||
/// <remarks>The cleaned up Uri has no virtual directory, no trailing slash, no .aspx extension, etc.</remarks>
|
||||
Uri Uri { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the decoded absolute path of the <see cref="Uri"/>
|
||||
/// </summary>
|
||||
string AbsolutePathDecoded { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="DomainAndUri"/> assigned (if any)
|
||||
/// </summary>
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -26,12 +27,16 @@ namespace Umbraco.Web.Routing
|
||||
public PublishedRequestBuilder(Uri uri, IFileService fileService)
|
||||
{
|
||||
Uri = uri;
|
||||
AbsolutePathDecoded = uri.GetAbsolutePathDecoded();
|
||||
_fileService = fileService;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Uri Uri { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string AbsolutePathDecoded { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public DomainAndUri Domain { get; private set; }
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Text;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
@@ -88,6 +88,10 @@ namespace Umbraco.Web
|
||||
// ie no virtual directory, no .aspx, lowercase...
|
||||
public Uri UriToUmbraco(Uri uri)
|
||||
{
|
||||
// TODO: Ideally we do this witout so many string allocations, we can use
|
||||
// techniques like StringSegment and Span. This is critical code that executes on every request.
|
||||
// not really sure we need ToLower.
|
||||
|
||||
// note: no need to decode uri here because we're returning a uri
|
||||
// so it will be re-encoded anyway
|
||||
var path = uri.GetSafeAbsolutePath();
|
||||
@@ -95,23 +99,11 @@ namespace Umbraco.Web
|
||||
path = path.ToLower();
|
||||
path = ToAppRelative(path); // strip vdir if any
|
||||
|
||||
//we need to check if the path is /default.aspx because this will occur when using a
|
||||
//web server pre IIS 7 when requesting the root document
|
||||
//if this is the case we need to change it to '/'
|
||||
if (path.StartsWith("/default.aspx", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
string rempath = path.Substring("/default.aspx".Length, path.Length - "/default.aspx".Length);
|
||||
path = rempath.StartsWith("/") ? rempath : "/" + rempath;
|
||||
}
|
||||
if (path != "/")
|
||||
{
|
||||
path = path.TrimEnd('/');
|
||||
}
|
||||
|
||||
//if any part of the path contains .aspx, replace it with nothing.
|
||||
//sometimes .aspx is not at the end since we might have /home/sub1.aspx/customtemplate
|
||||
path = path.Replace(".aspx", "");
|
||||
|
||||
return uri.Rewrite(path);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,9 @@ namespace Umbraco.Core
|
||||
public static string GetSafeAbsolutePath(this Uri uri)
|
||||
{
|
||||
if (uri.IsAbsoluteUri)
|
||||
{
|
||||
return uri.AbsolutePath;
|
||||
}
|
||||
|
||||
// cannot get .AbsolutePath on relative uri (InvalidOperation)
|
||||
var s = uri.OriginalString;
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Umbraco.Web.Routing
|
||||
}
|
||||
else
|
||||
{
|
||||
var route = frequest.Uri.GetAbsolutePathDecoded();
|
||||
var route = frequest.AbsolutePathDecoded;
|
||||
var pos = route.LastIndexOf('/');
|
||||
IPublishedContent node = null;
|
||||
while (pos > 1)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<PackageReference Include="MiniProfiler.AspNetCore" Version="4.2.1" />
|
||||
<PackageReference Include="Moq" Version="4.13.1" />
|
||||
<PackageReference Include="AutoFixture.NUnit3" Version="4.14.0" />
|
||||
<PackageReference Include="Moq" Version="4.14.5" />
|
||||
<PackageReference Include="Moq" Version="4.15.2" />
|
||||
<PackageReference Include="nunit" Version="3.12.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.8" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="Moq" Version="4.14.6" />
|
||||
<PackageReference Include="Moq" Version="4.15.2" />
|
||||
<PackageReference Include="nunit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
||||
@@ -79,13 +79,13 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing
|
||||
}
|
||||
|
||||
[TestCase("Index", "RenderNotFound", null, false)]
|
||||
[TestCase("index", "Render", "Index", true)]
|
||||
[TestCase("Index", "Render1", "Index", true)]
|
||||
[TestCase("Index", "render2", "Index", true)]
|
||||
[TestCase("NotFound", "Render", "Index", true)]
|
||||
[TestCase("NotFound", "Render1", "Index", true)]
|
||||
[TestCase("NotFound", "Render2", "Index", true)]
|
||||
[TestCase("Custom", "Render1", "Custom", true)]
|
||||
[TestCase("index", "Render", nameof(RenderController.Index), true)]
|
||||
[TestCase("Index", "Render1", nameof(RenderController.Index), true)]
|
||||
[TestCase("Index", "render2", nameof(Render2Controller.Index), true)]
|
||||
[TestCase("NotFound", "Render", nameof(RenderController.Index), true)]
|
||||
[TestCase("NotFound", "Render1", nameof(Render1Controller.Index), true)]
|
||||
[TestCase("NotFound", "Render2", nameof(Render2Controller.Index), true)]
|
||||
[TestCase("Custom", "Render1", nameof(Render1Controller.Custom), true)]
|
||||
public void Matches_Controller(string action, string controller, string resultAction, bool matches)
|
||||
{
|
||||
var evaluator = new HijackedRouteEvaluator(
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.ViewEngines;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Extensions;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Common.Controllers;
|
||||
using Umbraco.Web.Common.Routing;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Website.Controllers;
|
||||
using Umbraco.Web.Website.Routing;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing
|
||||
{
|
||||
[TestFixture]
|
||||
public class UmbracoRouteValueTransformerTests
|
||||
{
|
||||
private IOptions<GlobalSettings> GetGlobalSettings() => Options.Create(new GlobalSettings());
|
||||
|
||||
private UmbracoRouteValueTransformer GetTransformerWithRunState(
|
||||
IUmbracoContextAccessor ctx,
|
||||
IRoutableDocumentFilter filter = null,
|
||||
IPublishedRouter router = null,
|
||||
IUmbracoRouteValuesFactory routeValuesFactory = null)
|
||||
=> GetTransformer(ctx, Mock.Of<IRuntimeState>(x => x.Level == RuntimeLevel.Run), filter, router, routeValuesFactory);
|
||||
|
||||
private UmbracoRouteValueTransformer GetTransformer(
|
||||
IUmbracoContextAccessor ctx,
|
||||
IRuntimeState state,
|
||||
IRoutableDocumentFilter filter = null,
|
||||
IPublishedRouter router = null,
|
||||
IUmbracoRouteValuesFactory routeValuesFactory = null)
|
||||
{
|
||||
var transformer = new UmbracoRouteValueTransformer(
|
||||
new NullLogger<UmbracoRouteValueTransformer>(),
|
||||
ctx,
|
||||
router ?? Mock.Of<IPublishedRouter>(),
|
||||
GetGlobalSettings(),
|
||||
TestHelper.GetHostingEnvironment(),
|
||||
state,
|
||||
routeValuesFactory ?? Mock.Of<IUmbracoRouteValuesFactory>(),
|
||||
filter ?? Mock.Of<IRoutableDocumentFilter>(x => x.IsDocumentRequest(It.IsAny<string>()) == true));
|
||||
|
||||
return transformer;
|
||||
}
|
||||
|
||||
private IUmbracoContext GetUmbracoContext(bool hasContent)
|
||||
{
|
||||
IPublishedContentCache publishedContent = Mock.Of<IPublishedContentCache>(x => x.HasContent() == hasContent);
|
||||
var uri = new Uri("http://example.com");
|
||||
|
||||
IUmbracoContext umbracoContext = Mock.Of<IUmbracoContext>(x =>
|
||||
x.Content == publishedContent
|
||||
&& x.OriginalRequestUrl == uri
|
||||
&& x.CleanedUmbracoUrl == uri);
|
||||
|
||||
return umbracoContext;
|
||||
}
|
||||
|
||||
private UmbracoRouteValues GetRouteValues(IPublishedRequest request)
|
||||
=> new UmbracoRouteValues(
|
||||
request,
|
||||
ControllerExtensions.GetControllerName<TestController>(),
|
||||
typeof(TestController));
|
||||
|
||||
private IUmbracoRouteValuesFactory GetRouteValuesFactory(IPublishedRequest request)
|
||||
=> Mock.Of<IUmbracoRouteValuesFactory>(x => x.Create(It.IsAny<HttpContext>(), It.IsAny<RouteValueDictionary>(), It.IsAny<IPublishedRequest>()) == GetRouteValues(request));
|
||||
|
||||
private IPublishedRouter GetRouter(IPublishedRequest request)
|
||||
=> Mock.Of<IPublishedRouter>(x => x.RouteRequestAsync(It.IsAny<IPublishedRequestBuilder>(), It.IsAny<RouteRequestOptions>()) == Task.FromResult(request));
|
||||
|
||||
[Test]
|
||||
public async Task Noop_When_Runtime_Level_Not_Run()
|
||||
{
|
||||
UmbracoRouteValueTransformer transformer = GetTransformer(
|
||||
Mock.Of<IUmbracoContextAccessor>(x => x.UmbracoContext == null),
|
||||
Mock.Of<IRuntimeState>());
|
||||
|
||||
RouteValueDictionary result = await transformer.TransformAsync(new DefaultHttpContext(), new RouteValueDictionary());
|
||||
Assert.AreEqual(0, result.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Noop_When_No_Umbraco_Context()
|
||||
{
|
||||
UmbracoRouteValueTransformer transformer = GetTransformerWithRunState(
|
||||
Mock.Of<IUmbracoContextAccessor>(x => x.UmbracoContext == null));
|
||||
|
||||
RouteValueDictionary result = await transformer.TransformAsync(new DefaultHttpContext(), new RouteValueDictionary());
|
||||
Assert.AreEqual(0, result.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Noop_When_Not_Document_Request()
|
||||
{
|
||||
UmbracoRouteValueTransformer transformer = GetTransformerWithRunState(
|
||||
Mock.Of<IUmbracoContextAccessor>(x => x.UmbracoContext == Mock.Of<IUmbracoContext>()),
|
||||
Mock.Of<IRoutableDocumentFilter>(x => x.IsDocumentRequest(It.IsAny<string>()) == false));
|
||||
|
||||
RouteValueDictionary result = await transformer.TransformAsync(new DefaultHttpContext(), new RouteValueDictionary());
|
||||
Assert.AreEqual(0, result.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task NoContentController_Values_When_No_Content()
|
||||
{
|
||||
IUmbracoContext umbracoContext = GetUmbracoContext(false);
|
||||
|
||||
UmbracoRouteValueTransformer transformer = GetTransformerWithRunState(
|
||||
Mock.Of<IUmbracoContextAccessor>(x => x.UmbracoContext == umbracoContext));
|
||||
|
||||
RouteValueDictionary result = await transformer.TransformAsync(new DefaultHttpContext(), new RouteValueDictionary());
|
||||
Assert.AreEqual(2, result.Count);
|
||||
Assert.AreEqual(ControllerExtensions.GetControllerName<RenderNoContentController>(), result["controller"]);
|
||||
Assert.AreEqual(nameof(RenderNoContentController.Index), result["action"]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Assigns_PublishedRequest_To_UmbracoContext()
|
||||
{
|
||||
IUmbracoContext umbracoContext = GetUmbracoContext(true);
|
||||
IPublishedRequest request = Mock.Of<IPublishedRequest>();
|
||||
|
||||
UmbracoRouteValueTransformer transformer = GetTransformerWithRunState(
|
||||
Mock.Of<IUmbracoContextAccessor>(x => x.UmbracoContext == umbracoContext),
|
||||
router: GetRouter(request),
|
||||
routeValuesFactory: GetRouteValuesFactory(request));
|
||||
|
||||
RouteValueDictionary result = await transformer.TransformAsync(new DefaultHttpContext(), new RouteValueDictionary());
|
||||
Assert.AreEqual(request, umbracoContext.PublishedRequest);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Assigns_Values_To_RouteValueDictionary()
|
||||
{
|
||||
IUmbracoContext umbracoContext = GetUmbracoContext(true);
|
||||
IPublishedRequest request = Mock.Of<IPublishedRequest>();
|
||||
UmbracoRouteValues routeValues = GetRouteValues(request);
|
||||
|
||||
UmbracoRouteValueTransformer transformer = GetTransformerWithRunState(
|
||||
Mock.Of<IUmbracoContextAccessor>(x => x.UmbracoContext == umbracoContext),
|
||||
router: GetRouter(request),
|
||||
routeValuesFactory: GetRouteValuesFactory(request));
|
||||
|
||||
RouteValueDictionary result = await transformer.TransformAsync(new DefaultHttpContext(), new RouteValueDictionary());
|
||||
|
||||
Assert.AreEqual(routeValues.ControllerName, result["controller"]);
|
||||
Assert.AreEqual(routeValues.ActionName, result["action"]);
|
||||
}
|
||||
|
||||
private class TestController : RenderController
|
||||
{
|
||||
public TestController(ILogger<RenderController> logger, ICompositeViewEngine compositeViewEngine, IUmbracoContextAccessor umbracoContextAccessor)
|
||||
: base(logger, compositeViewEngine, umbracoContextAccessor)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
@@ -18,16 +18,17 @@ using Umbraco.Web.Website.Routing;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class UmbracoRouteValuesFactoryTests
|
||||
{
|
||||
private UmbracoRouteValuesFactory GetFactory(IPublishedRouter router, out UmbracoRenderingDefaults renderingDefaults)
|
||||
private UmbracoRouteValuesFactory GetFactory(out Mock<IPublishedRouter> publishedRouter, out UmbracoRenderingDefaults renderingDefaults)
|
||||
{
|
||||
var builder = new PublishedRequestBuilder(new Uri("https://example.com"), Mock.Of<IFileService>());
|
||||
builder.SetPublishedContent(Mock.Of<IPublishedContent>());
|
||||
IPublishedRequest request = builder.Build();
|
||||
|
||||
var publishedRouter = new Mock<IPublishedRouter>();
|
||||
publishedRouter = new Mock<IPublishedRouter>();
|
||||
publishedRouter.Setup(x => x.UpdateRequestToNotFound(It.IsAny<IPublishedRequest>()))
|
||||
.Returns((IPublishedRequest r) => builder)
|
||||
.Verifiable();
|
||||
@@ -53,12 +54,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing
|
||||
builder.SetPublishedContent(Mock.Of<IPublishedContent>());
|
||||
IPublishedRequest request = builder.Build();
|
||||
|
||||
var publishedRouter = new Mock<IPublishedRouter>();
|
||||
publishedRouter.Setup(x => x.UpdateRequestToNotFound(It.IsAny<IPublishedRequest>()))
|
||||
.Returns((IPublishedRequest r) => builder)
|
||||
.Verifiable();
|
||||
|
||||
UmbracoRouteValuesFactory factory = GetFactory(publishedRouter.Object, out _);
|
||||
UmbracoRouteValuesFactory factory = GetFactory(out Mock<IPublishedRouter> publishedRouter, out _);
|
||||
|
||||
UmbracoRouteValues result = factory.Create(new DefaultHttpContext(), new RouteValueDictionary(), request);
|
||||
|
||||
@@ -74,7 +70,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing
|
||||
builder.SetTemplate(Mock.Of<ITemplate>());
|
||||
IPublishedRequest request = builder.Build();
|
||||
|
||||
UmbracoRouteValuesFactory factory = GetFactory(Mock.Of<IPublishedRouter>(), out UmbracoRenderingDefaults renderingDefaults);
|
||||
UmbracoRouteValuesFactory factory = GetFactory(out _, out UmbracoRenderingDefaults renderingDefaults);
|
||||
|
||||
var routeVals = new RouteValueDictionary();
|
||||
UmbracoRouteValues result = factory.Create(new DefaultHttpContext(), routeVals, request);
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
<PackageReference Include="Microsoft.Owin.Testing" Version="4.1.1" />
|
||||
<PackageReference Include="Microsoft.Web.Infrastructure" Version="1.0.0.0" />
|
||||
<PackageReference Include="MiniProfiler" Version="4.2.1" />
|
||||
<PackageReference Include="Moq" Version="4.14.6" />
|
||||
<PackageReference Include="Moq" Version="4.15.2" />
|
||||
<PackageReference Include="NPoco" Version="4.0.2" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||
@@ -307,7 +307,7 @@
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="IO" />
|
||||
<Folder Include="IO\" />
|
||||
</ItemGroup>
|
||||
<!-- get NuGet packages directory -->
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
@@ -61,7 +61,7 @@ namespace Umbraco.Web.Common.AspNetCore
|
||||
|
||||
public Uri GetApplicationUrl()
|
||||
{
|
||||
//Fixme: This causes problems with site swap on azure because azure pre-warms a site by calling into `localhost` and when it does that
|
||||
// Fixme: This causes problems with site swap on azure because azure pre-warms a site by calling into `localhost` and when it does that
|
||||
// it changes the URL to `localhost:80` which actually doesn't work for pinging itself, it only works internally in Azure. The ironic part
|
||||
// about this is that this is here specifically for the slot swap scenario https://issues.umbraco.org/issue/U4-10626
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Umbraco.Web.Common.Routing
|
||||
{
|
||||
public interface IRoutableDocumentFilter
|
||||
{
|
||||
bool IsDocumentRequest(string absPath);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Web.Common.Routing
|
||||
/// <remarks>
|
||||
/// There are various checks to determine if this is a front-end request such as checking if the request is part of any reserved paths or existing MVC routes.
|
||||
/// </remarks>
|
||||
public sealed class RoutableDocumentFilter
|
||||
public sealed class RoutableDocumentFilter : IRoutableDocumentFilter
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, bool> _routeChecks = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Umbraco.Web
|
||||
public class UmbracoContext : DisposableObjectSlim, IDisposeOnRequestEnd, IUmbracoContext
|
||||
{
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly UriUtility _uriUtility;
|
||||
private readonly ICookieManager _cookieManager;
|
||||
private readonly IRequestAccessor _requestAccessor;
|
||||
private readonly Lazy<IPublishedSnapshot> _publishedSnapshot;
|
||||
@@ -23,6 +24,8 @@ namespace Umbraco.Web
|
||||
private bool? _previewing;
|
||||
private readonly IBackOfficeSecurity _backofficeSecurity;
|
||||
private readonly UmbracoRequestPaths _umbracoRequestPaths;
|
||||
private Uri _originalRequestUrl;
|
||||
private Uri _cleanedUmbracoUrl;
|
||||
|
||||
// initializes a new instance of the UmbracoContext class
|
||||
// internal for unit tests
|
||||
@@ -43,8 +46,8 @@ namespace Umbraco.Web
|
||||
throw new ArgumentNullException(nameof(publishedSnapshotService));
|
||||
}
|
||||
|
||||
VariationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor));
|
||||
|
||||
VariationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor));
|
||||
_uriUtility = uriUtility;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_cookieManager = cookieManager;
|
||||
_requestAccessor = requestAccessor;
|
||||
@@ -56,15 +59,6 @@ namespace Umbraco.Web
|
||||
|
||||
// beware - we cannot expect a current user here, so detecting preview mode must be a lazy thing
|
||||
_publishedSnapshot = new Lazy<IPublishedSnapshot>(() => publishedSnapshotService.CreatePublishedSnapshot(PreviewToken));
|
||||
|
||||
// set the urls...
|
||||
// NOTE: The request will not be available during app startup so we can only set this to an absolute URL of localhost, this
|
||||
// is a work around to being able to access the UmbracoContext during application startup and this will also ensure that people
|
||||
// 'could' still generate URLs during startup BUT any domain driven URL generation will not work because it is NOT possible to get
|
||||
// the current domain during application startup.
|
||||
// see: http://issues.umbraco.org/issue/U4-1890
|
||||
OriginalRequestUrl = _requestAccessor.GetRequestUrl() ?? new Uri("http://localhost");
|
||||
CleanedUmbracoUrl = uriUtility.UriToUmbraco(OriginalRequestUrl);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -79,10 +73,17 @@ namespace Umbraco.Web
|
||||
internal Guid UmbracoRequestId { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Uri OriginalRequestUrl { get; }
|
||||
// set the urls lazily, no need to allocate until they are needed...
|
||||
// NOTE: The request will not be available during app startup so we can only set this to an absolute URL of localhost, this
|
||||
// is a work around to being able to access the UmbracoContext during application startup and this will also ensure that people
|
||||
// 'could' still generate URLs during startup BUT any domain driven URL generation will not work because it is NOT possible to get
|
||||
// the current domain during application startup.
|
||||
// see: http://issues.umbraco.org/issue/U4-1890
|
||||
public Uri OriginalRequestUrl => _originalRequestUrl ?? (_originalRequestUrl = _requestAccessor.GetRequestUrl() ?? new Uri("http://localhost"));
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Uri CleanedUmbracoUrl { get; }
|
||||
// set the urls lazily, no need to allocate until they are needed...
|
||||
public Uri CleanedUmbracoUrl => _cleanedUmbracoUrl ?? (_cleanedUmbracoUrl = _uriUtility.UriToUmbraco(OriginalRequestUrl));
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IPublishedSnapshot PublishedSnapshot => _publishedSnapshot.Value;
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Umbraco.Web.Website.DependencyInjection
|
||||
builder.Services.AddSingleton<HijackedRouteEvaluator>();
|
||||
builder.Services.AddSingleton<IUmbracoRouteValuesFactory, UmbracoRouteValuesFactory>();
|
||||
builder.Services.AddSingleton<IUmbracoRenderingDefaults, UmbracoRenderingDefaults>();
|
||||
builder.Services.AddSingleton<RoutableDocumentFilter>();
|
||||
builder.Services.AddSingleton<IRoutableDocumentFilter, RoutableDocumentFilter>();
|
||||
|
||||
builder.AddDistributedCache();
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Umbraco.Web.Website.Routing
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly IRuntimeState _runtime;
|
||||
private readonly IUmbracoRouteValuesFactory _routeValuesFactory;
|
||||
private readonly RoutableDocumentFilter _routableDocumentFilter;
|
||||
private readonly IRoutableDocumentFilter _routableDocumentFilter;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoRouteValueTransformer"/> class.
|
||||
@@ -47,16 +47,21 @@ namespace Umbraco.Web.Website.Routing
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
IRuntimeState runtime,
|
||||
IUmbracoRouteValuesFactory routeValuesFactory,
|
||||
RoutableDocumentFilter routableDocumentFilter)
|
||||
IRoutableDocumentFilter routableDocumentFilter)
|
||||
{
|
||||
_logger = logger;
|
||||
_umbracoContextAccessor = umbracoContextAccessor;
|
||||
_publishedRouter = publishedRouter;
|
||||
if (globalSettings is null)
|
||||
{
|
||||
throw new System.ArgumentNullException(nameof(globalSettings));
|
||||
}
|
||||
|
||||
_logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
|
||||
_umbracoContextAccessor = umbracoContextAccessor ?? throw new System.ArgumentNullException(nameof(umbracoContextAccessor));
|
||||
_publishedRouter = publishedRouter ?? throw new System.ArgumentNullException(nameof(publishedRouter));
|
||||
_globalSettings = globalSettings.Value;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_runtime = runtime;
|
||||
_routeValuesFactory = routeValuesFactory;
|
||||
_routableDocumentFilter = routableDocumentFilter;
|
||||
_hostingEnvironment = hostingEnvironment ?? throw new System.ArgumentNullException(nameof(hostingEnvironment));
|
||||
_runtime = runtime ?? throw new System.ArgumentNullException(nameof(runtime));
|
||||
_routeValuesFactory = routeValuesFactory ?? throw new System.ArgumentNullException(nameof(routeValuesFactory));
|
||||
_routableDocumentFilter = routableDocumentFilter ?? throw new System.ArgumentNullException(nameof(routableDocumentFilter));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -113,9 +118,10 @@ namespace Umbraco.Web.Website.Routing
|
||||
// an immutable object. The only way to make this better would be to have a RouteRequest
|
||||
// as part of UmbracoContext but then it will require a PublishedRouter dependency so not sure that's worth it.
|
||||
// Maybe could be a one-time Set method instead?
|
||||
IPublishedRequest publishedRequest = umbracoContext.PublishedRequest = await _publishedRouter.RouteRequestAsync(requestBuilder, new RouteRequestOptions(RouteDirection.Inbound));
|
||||
IPublishedRequest routedRequest = await _publishedRouter.RouteRequestAsync(requestBuilder, new RouteRequestOptions(RouteDirection.Inbound));
|
||||
umbracoContext.PublishedRequest = routedRequest;
|
||||
|
||||
return publishedRequest;
|
||||
return routedRequest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,6 @@ namespace Umbraco.Web
|
||||
// 'could' still generate URLs during startup BUT any domain driven URL generation will not work because it is NOT possible to get
|
||||
// the current domain during application startup.
|
||||
// see: http://issues.umbraco.org/issue/U4-1890
|
||||
//
|
||||
OriginalRequestUrl = GetRequestFromContext()?.Url ?? new Uri("http://localhost");
|
||||
CleanedUmbracoUrl = uriUtility.UriToUmbraco(OriginalRequestUrl);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user