V13: Set request culture for VirtualPageController (#16572)

* Rename FindDomain to FindAndSetDomain

* Ensure VariationContext and PublishedRequest is updated for virtual page controller
This commit is contained in:
Mole
2024-06-07 12:49:13 +02:00
committed by GitHub
parent 5f8eac0464
commit 5ae5fe338a
8 changed files with 82 additions and 17 deletions

View File

@@ -47,4 +47,37 @@ public interface IPublishedRouter
/// </para>
/// </remarks>
Task<IPublishedRequest> UpdateRequestAsync(IPublishedRequest request, IPublishedContent? publishedContent);
/// <summary>
/// Finds the site root (if any) matching the http request, and updates the PublishedRequest and VariationContext accordingly.
/// <remarks>
/// <para>
/// This method is used for VirtualPage routing.
/// </para>
/// <para>
/// In this case we do not want to run the entire routing pipeline since ContentFinders are not needed here.
/// However, we do want to set the culture on VariationContext and PublishedRequest to the values specified by the domains.
/// </para>
/// </remarks>
/// </summary>
/// <param name="request">The request to update the culture on domain on</param>
/// <returns>True if a domain was found otherwise false.</returns>
bool RouteDomain(IPublishedRequestBuilder request) => false;
/// <summary>
/// Finds the site root (if any) matching the http request, and updates the VariationContext accordingly.
/// </summary>
/// <remarks>
/// <para>
/// This is used for VirtualPage routing.
/// </para>
/// <para>
/// This is required to set the culture on VariationContext to the values specified by the domains, before the FindContent method is called.
/// In order to allow the FindContent implementer to correctly find content based off the culture. Before the PublishedRequest is built.
/// </para>
/// </remarks>
/// <param name="uri">The URI to resolve the domain from.</param>
/// <returns>True if a domain was found, otherwise false.</returns>
bool UpdateVariationContext(Uri uri) => false;
}

View File

@@ -108,7 +108,7 @@ public class PublishedRouter : IPublishedRouter
// find domain
if (builder.Domain == null)
{
FindDomain(builder);
FindAndSetDomain(builder);
}
await RouteRequestInternalAsync(builder);
@@ -185,7 +185,7 @@ public class PublishedRouter : IPublishedRouter
private async Task<IPublishedRequest> TryRouteRequest(IPublishedRequestBuilder request)
{
FindDomain(request);
FindAndSetDomain(request);
if (request.IsRedirect())
{
@@ -270,18 +270,31 @@ public class PublishedRouter : IPublishedRouter
// to find out the appropriate template
}
/// <summary>
/// Finds the site root (if any) matching the http request, and updates the PublishedRequest accordingly.
/// </summary>
/// <returns>A value indicating whether a domain was found.</returns>
internal bool FindDomain(IPublishedRequestBuilder request)
/// <inheritdoc />
public bool RouteDomain(IPublishedRequestBuilder request)
{
var found = FindAndSetDomain(request);
HandleWildcardDomains(request);
SetVariationContext(request.Culture);
return found;
}
/// <inheritdoc />
public bool UpdateVariationContext(Uri uri)
{
DomainAndUri? domain = FindDomain(uri, out _);
SetVariationContext(domain?.Culture);
return domain?.Culture is not null;
}
private DomainAndUri? FindDomain(Uri uri, out string? defaultCulture)
{
const string tracePrefix = "FindDomain: ";
// note - we are not handling schemes nor ports here.
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.LogDebug("{TracePrefix}Uri={RequestUri}", tracePrefix, request.Uri);
_logger.LogDebug("{TracePrefix}Uri={RequestUri}", tracePrefix, uri);
}
IUmbracoContext umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext();
@@ -315,10 +328,20 @@ public class PublishedRouter : IPublishedRouter
domains = domains?.Where(IsPublishedContentDomain).ToList();
var defaultCulture = domainsCache?.DefaultCulture;
defaultCulture = domainsCache?.DefaultCulture;
return DomainUtilities.SelectDomain(domains, uri, defaultCulture: defaultCulture);
}
/// <summary>
/// Finds the site root (if any) matching the http request, and updates the PublishedRequest accordingly.
/// </summary>
/// <returns>A value indicating whether a domain was found.</returns>
internal bool FindAndSetDomain(IPublishedRequestBuilder request)
{
const string tracePrefix = "FindDomain: ";
// try to find a domain matching the current request
DomainAndUri? domainAndUri = DomainUtilities.SelectDomain(domains, request.Uri, defaultCulture: defaultCulture);
DomainAndUri? domainAndUri = FindDomain(request.Uri, out var defaultCulture);
// handle domain - always has a contentId and a culture
if (domainAndUri != null)

View File

@@ -1,9 +1,11 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Web.Common.Controllers;
using Umbraco.Cms.Web.Common.Routing;
@@ -40,6 +42,12 @@ public class UmbracoVirtualPageFilterAttribute : Attribute, IAsyncActionFilter
if (endpoint != null)
{
IUmbracoVirtualPageRoute umbracoVirtualPageRoute = context.HttpContext.RequestServices.GetRequiredService<IUmbracoVirtualPageRoute>();
IPublishedRouter publishedRouter = context.HttpContext.RequestServices.GetRequiredService<IPublishedRouter>();
UriUtility uriUtility = context.HttpContext.RequestServices.GetRequiredService<UriUtility>();
var originalRequestUrl = new Uri(context.HttpContext.Request.GetEncodedUrl());
Uri cleanedUri = uriUtility.UriToUmbraco(originalRequestUrl);
publishedRouter.UpdateVariationContext(cleanedUri);
IPublishedContent? publishedContent = umbracoVirtualPageRoute.FindContent(endpoint, context);

View File

@@ -155,6 +155,7 @@ public class UmbracoVirtualPageRoute : IUmbracoVirtualPageRoute
IPublishedRequestBuilder requestBuilder = await _publishedRouter.CreateRequestAsync(cleanedUrl);
requestBuilder.SetPublishedContent(publishedContent);
_publishedRouter.RouteDomain(requestBuilder);
return requestBuilder.Build();
}

View File

@@ -31,7 +31,7 @@ public class ContentFinderByAliasWithDomainsTests : UrlRoutingTestBase
var request = await publishedRouter.CreateRequestAsync(umbracoContext.CleanedUmbracoUrl);
// must lookup domain
publishedRouter.FindDomain(request);
publishedRouter.FindAndSetDomain(request);
if (expectedNode > 0)
{

View File

@@ -207,7 +207,7 @@ public class ContentFinderByUrlWithDomainsTests : UrlRoutingTestBase
var frequest = await publishedRouter.CreateRequestAsync(umbracoContext.CleanedUmbracoUrl);
// must lookup domain else lookup by URL fails
publishedRouter.FindDomain(frequest);
publishedRouter.FindAndSetDomain(frequest);
var lookup = new ContentFinderByUrl(Mock.Of<ILogger<ContentFinderByUrl>>(), umbracoContextAccessor);
var result = await lookup.TryFindContent(frequest);
@@ -245,7 +245,7 @@ public class ContentFinderByUrlWithDomainsTests : UrlRoutingTestBase
var frequest = await publishedRouter.CreateRequestAsync(umbracoContext.CleanedUmbracoUrl);
// must lookup domain else lookup by URL fails
publishedRouter.FindDomain(frequest);
publishedRouter.FindAndSetDomain(frequest);
Assert.AreEqual(expectedCulture, frequest.Culture);
var lookup = new ContentFinderByUrl(Mock.Of<ILogger<ContentFinderByUrl>>(), umbracoContextAccessor);

View File

@@ -261,7 +261,7 @@ public class DomainsAndCulturesTests : UrlRoutingTestBase
var frequest = await publishedRouter.CreateRequestAsync(umbracoContext.CleanedUmbracoUrl);
// lookup domain
publishedRouter.FindDomain(frequest);
publishedRouter.FindAndSetDomain(frequest);
Assert.AreEqual(expectedCulture, frequest.Culture);
@@ -310,7 +310,7 @@ public class DomainsAndCulturesTests : UrlRoutingTestBase
var frequest = await publishedRouter.CreateRequestAsync(umbracoContext.CleanedUmbracoUrl);
// lookup domain
publishedRouter.FindDomain(frequest);
publishedRouter.FindAndSetDomain(frequest);
// find document
var finder = new ContentFinderByUrl(Mock.Of<ILogger<ContentFinderByUrl>>(), umbracoContextAccessor);
@@ -345,7 +345,7 @@ public class DomainsAndCulturesTests : UrlRoutingTestBase
var frequest = await publishedRouter.CreateRequestAsync(umbracoContext.CleanedUmbracoUrl);
// lookup domain
publishedRouter.FindDomain(frequest);
publishedRouter.FindAndSetDomain(frequest);
Assert.IsNotNull(frequest.Domain);
Assert.AreEqual(expectedCulture, frequest.Culture);

View File

@@ -62,7 +62,7 @@ public class UrlsWithNestedDomains : UrlRoutingTestBase
var publishedRouter = CreatePublishedRouter(umbracoContextAccessor);
var frequest = await publishedRouter.CreateRequestAsync(umbracoContext.CleanedUmbracoUrl);
publishedRouter.FindDomain(frequest);
publishedRouter.FindAndSetDomain(frequest);
Assert.IsTrue(frequest.HasDomain());
// check that it's been routed