internal UrlInfo GetUrlFromRoute( string route, IUmbracoContext umbracoContext, int id, Uri current, UrlMode mode, string culture) { if (string.IsNullOrWhiteSpace(route)) { _logger.LogDebug( "Couldn't find any page with nodeId={NodeId}. This is most likely caused by the page not being published.", id); return(null); } // extract domainUri and path // route is /<path> or <domainRootId>/<path> var pos = route.IndexOf('/'); var path = pos == 0 ? route : route.Substring(pos); DomainAndUri domainUri = pos == 0 ? null : DomainUtilities.DomainForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, int.Parse(route.Substring(0, pos), CultureInfo.InvariantCulture), current, culture); var defaultCulture = _localizationService.GetDefaultLanguageIsoCode(); if (domainUri is not null || string.IsNullOrEmpty(culture) || culture.Equals(defaultCulture, StringComparison.InvariantCultureIgnoreCase)) { var url = AssembleUrl(domainUri, path, current, mode).ToString(); return(UrlInfo.Url(url, culture)); } return(null); }
/// <summary> /// Initializes a new instance of the <see cref="PublishedRequest"/> class. /// </summary> public PublishedRequest(Uri uri, string absolutePathDecoded, IPublishedContent publishedContent, bool isInternalRedirect, ITemplate template, DomainAndUri domain, string culture, string redirectUrl, int?responseStatusCode, IReadOnlyList <string> cacheExtensions, IReadOnlyDictionary <string, string> headers, bool setNoCacheHeader, bool ignorePublishedContentCollisions) { Uri = uri ?? throw new ArgumentNullException(nameof(uri)); AbsolutePathDecoded = absolutePathDecoded ?? throw new ArgumentNullException(nameof(absolutePathDecoded)); PublishedContent = publishedContent; IsInternalRedirect = isInternalRedirect; Template = template; Domain = domain; Culture = culture; RedirectUrl = redirectUrl; ResponseStatusCode = responseStatusCode; CacheExtensions = cacheExtensions; Headers = headers; SetNoCacheHeader = setNoCacheHeader; IgnorePublishedContentCollisions = ignorePublishedContentCollisions; }
Uri AssembleUrl(DomainAndUri domainUri, string path, Uri current, UrlMode mode) { Uri uri; // ignore vdir at that point, UriFromUmbraco will do it if (domainUri == null) // no domain was found { if (current == null) { mode = UrlMode.Relative; // best we can do } switch (mode) { case UrlMode.Absolute: uri = new Uri(current.GetLeftPart(UriPartial.Authority) + path); break; case UrlMode.Relative: case UrlMode.Auto: uri = new Uri(path, UriKind.Relative); break; default: throw new ArgumentOutOfRangeException(nameof(mode)); } } else // a domain was found { if (mode == UrlMode.Auto) { //this check is a little tricky, we can't just compare domains if (current != null && domainUri.Uri.GetLeftPart(UriPartial.Authority) == current.GetLeftPart(UriPartial.Authority)) { mode = UrlMode.Relative; } else { mode = UrlMode.Absolute; } } switch (mode) { case UrlMode.Absolute: uri = new Uri(CombinePaths(domainUri.Uri.GetLeftPart(UriPartial.Path), path)); break; case UrlMode.Relative: uri = new Uri(CombinePaths(domainUri.Uri.AbsolutePath, path), UriKind.Relative); break; default: throw new ArgumentOutOfRangeException(nameof(mode)); } } // UriFromUmbraco will handle vdir // meaning it will add vdir into domain URLs too! return(_uriUtility.UriFromUmbraco(uri, _requestSettings)); }
private static bool MatchesCulture(DomainAndUri domain, string?culture) => culture == null || domain.Culture.InvariantEquals(culture);
private static bool IsBaseOf(DomainAndUri domain, Uri uri) => domain.Uri.EndPathWithSlash().IsBaseOf(uri);
/// <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) { const string tracePrefix = "FindDomain: "; // note - we are not handling schemes nor ports here. _logger.LogDebug("{TracePrefix}Uri={RequestUri}", tracePrefix, request.Uri); var umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext(); IDomainCache domainsCache = umbracoContext.PublishedSnapshot.Domains; var domains = domainsCache.GetAll(includeWildcards: false).ToList(); // determines whether a domain corresponds to a published document, since some // domains may exist but on a document that has been unpublished - as a whole - or // that is not published for the domain's culture - in which case the domain does // not apply bool IsPublishedContentDomain(Domain domain) { // just get it from content cache - optimize there, not here IPublishedContent domainDocument = umbracoContext.PublishedSnapshot.Content.GetById(domain.ContentId); // not published - at all if (domainDocument == null) { return(false); } // invariant - always published if (!domainDocument.ContentType.VariesByCulture()) { return(true); } // variant, ensure that the culture corresponding to the domain's language is published return(domainDocument.Cultures.ContainsKey(domain.Culture)); } domains = domains.Where(IsPublishedContentDomain).ToList(); var defaultCulture = domainsCache.DefaultCulture; // try to find a domain matching the current request DomainAndUri domainAndUri = DomainUtilities.SelectDomain(domains, request.Uri, defaultCulture: defaultCulture); // handle domain - always has a contentId and a culture if (domainAndUri != null) { // matching an existing domain _logger.LogDebug("{TracePrefix}Matches domain={Domain}, rootId={RootContentId}, culture={Culture}", tracePrefix, domainAndUri.Name, domainAndUri.ContentId, domainAndUri.Culture); request.SetDomain(domainAndUri); // canonical? not implemented at the moment // if (...) // { // _pcr.RedirectUrl = "..."; // return true; // } } else { // not matching any existing domain _logger.LogDebug("{TracePrefix}Matches no domain", tracePrefix); request.SetCulture(defaultCulture ?? CultureInfo.CurrentUICulture.Name); } _logger.LogDebug("{TracePrefix}Culture={CultureName}", tracePrefix, request.Culture); return(request.Domain != null); }