Files
Umbraco-CMS/src/Umbraco.Web/Routing/ContentFinderByRedirectUrl.cs
Sebastiaan Janssen b9fcda8f39 U4-8361 301 Url Tracking
Adds the ability to add certain headers to a PublishedContentRequest - these are internal for now until we're sure we want to expose them
Adds response headers to tell browsers not to cache the 301 redirects so people can easily change their mind later
2016-08-02 17:01:32 +02:00

62 lines
3.1 KiB
C#

using System.Collections.Generic;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Logging;
namespace Umbraco.Web.Routing
{
/// <summary>
/// Provides an implementation of <see cref="IContentFinder"/> that handles page url rewrites
/// that are stored when moving, saving, or deleting a node.
/// </summary>
/// <remarks>
/// <para>Assigns a permanent redirect notification to the request.</para>
/// </remarks>
public class ContentFinderByRedirectUrl : IContentFinder
{
/// <summary>
/// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
/// </summary>
/// <param name="contentRequest">The <c>PublishedContentRequest</c>.</param>
/// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
/// <remarks>Optionally, can also assign the template or anything else on the document request, although that is not required.</remarks>
public bool TryFindContent(PublishedContentRequest contentRequest)
{
var route = contentRequest.HasDomain
? contentRequest.UmbracoDomain.RootContentId + DomainHelper.PathRelativeToDomain(contentRequest.DomainUri, contentRequest.Uri.GetAbsolutePathDecoded())
: contentRequest.Uri.GetAbsolutePathDecoded();
var service = contentRequest.RoutingContext.UmbracoContext.Application.Services.RedirectUrlService;
var redirectUrl = service.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
contentRequest.Cacheability = HttpCacheability.NoCache;
contentRequest.CacheExtensions = new List<string> { "no-store, must-revalidate" };
contentRequest.Headers = new Dictionary<string, string> { { "Pragma", "no-cache" }, { "Expires", "0" } };
if (redirectUrl == null)
{
LogHelper.Debug<ContentFinderByRedirectUrl>("No match for route: \"{0}\".", () => route);
return false;
}
var content = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetById(redirectUrl.ContentId);
var url = content == null ? "#" : content.Url;
if (url.StartsWith("#"))
{
LogHelper.Debug<ContentFinderByRedirectUrl>("Route \"{0}\" matches content {1} which has no url.",
() => route, () => redirectUrl.ContentId);
return false;
}
LogHelper.Debug<ContentFinderByRedirectUrl>("Route \"{0}\" matches content {1} with url \"{2}\", redirecting.",
() => route, () => content.Id, () => url);
contentRequest.SetRedirectPermanent(url);
return true;
}
}
}