using System.Collections.Generic; using System.Web; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Services; namespace Umbraco.Web.Routing { /// /// Provides an implementation of that handles page url rewrites /// that are stored when moving, saving, or deleting a node. /// /// /// Assigns a permanent redirect notification to the request. /// public class ContentFinderByRedirectUrl : IContentFinder { private readonly IRedirectUrlService _redirectUrlService; private readonly ILogger _logger; public ContentFinderByRedirectUrl(IRedirectUrlService redirectUrlService, ILogger logger) { _redirectUrlService = redirectUrlService; _logger = logger; } /// /// Tries to find and assign an Umbraco document to a PublishedContentRequest. /// /// The PublishedContentRequest. /// A value indicating whether an Umbraco document was found and assigned. /// Optionally, can also assign the template or anything else on the document request, although that is not required. public bool TryFindContent(PublishedRequest frequest) { var route = frequest.HasDomain ? frequest.Domain.ContentId + DomainHelper.PathRelativeToDomain(frequest.Domain.Uri, frequest.Uri.GetAbsolutePathDecoded()) : frequest.Uri.GetAbsolutePathDecoded(); var redirectUrl = _redirectUrlService.GetMostRecentRedirectUrl(route); // From: http://stackoverflow.com/a/22468386/5018 // See http://issues.umbraco.org/issue/U4-8361#comment=67-30532 // Setting automatic 301 redirects to not be cached because browsers cache these very aggressively which then leads // to problems if you rename a page back to it's original name or create a new page with the original name frequest.Cacheability = HttpCacheability.NoCache; frequest.CacheExtensions = new List { "no-store, must-revalidate" }; frequest.Headers = new Dictionary { { "Pragma", "no-cache" }, { "Expires", "0" } }; if (redirectUrl == null) { _logger.Debug(() => $"No match for route: \"{route}\"."); return false; } var content = frequest.UmbracoContext.ContentCache.GetById(redirectUrl.ContentId); var url = content == null ? "#" : content.Url; if (url.StartsWith("#")) { _logger.Debug(() => $"Route \"{route}\" matches content {redirectUrl.ContentId} which has no url."); return false; } _logger.Debug(() => $"Route \"{route}\" matches content {content.Id} with url \"{url}\", redirecting."); frequest.SetRedirectPermanent(url); return true; } } }