Skip to content

Instantly share code, notes, and snippets.

@steliodibello
Created November 24, 2023 15:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steliodibello/f849cd443471650ddcacbf3ad37d75d4 to your computer and use it in GitHub Desktop.
Save steliodibello/f849cd443471650ddcacbf3ad37d75d4 to your computer and use it in GitHub Desktop.
using SharedSource.RedirectModule.Classes;
using SharedSource.RedirectModule.Helpers;
using Sitecore.Data;
using Sitecore.Data.Items;
using Sitecore.Links;
using Sitecore.Rules;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace XXXX.Foundation.Redirect.Pipelines.GetRedirectUrl
{
public class GetRedirectUrlProcessor
{
protected readonly IRedirectRepository RedirectRepository;
public GetRedirectUrlProcessor()
{
RedirectRepository = new RedirectRepository();
}
public void Process(GetRedirectUrlArgs args)
{
// Check for exact matches - priority over pattern matches.
if (Sitecore.Configuration.Settings.GetBoolSetting(Constants.Settings.RedirExactMatch, true))
{
args = CheckForDirectMatch(args.Database, args.RequestUrl, args.RequestPath, args);
if (!string.IsNullOrEmpty(args.RedirectUrl) || args.RedirectItem != null)
{
return;
}
}
// Next, we check for pattern matches because we didn't hit on an exact match.
if (Sitecore.Configuration.Settings.GetBoolSetting(Constants.Settings.RedirPatternMatch, true))
{
args = CheckForRegExMatch(args.Database, args.RequestUrl, args.RequestPathAndQuery, args);
if (!string.IsNullOrEmpty(args.RedirectUrl) || args.RedirectItem != null)
{
return;
}
}
// Rule matches prioriity on pattern match.
if (Sitecore.Configuration.Settings.GetBoolSetting(Constants.Settings.RedirRuleMatch, true))
{
args = CheckForRulesMatch(args.Database, args.RequestUrl, args.RequestPathAndQuery, args);
}
}
private bool IsMediaDirectMatch(string incomingUrl, string toMatchUrl)
{
if (incomingUrl == toMatchUrl)
{
return true;
}
if (toMatchUrl.StartsWith("sitecore/media library/"))
{
toMatchUrl = toMatchUrl.Replace("sitecore/media library", "/-/media");
}
if (!toMatchUrl.StartsWith("/-/media"))
{
return false;
}
if (incomingUrl == toMatchUrl)
{
return true;
}
// lastly, try matching by stripping extension and query string params
var regex = @"^(.*?)(\.[\w]{3,4}([?].+)?)?$";
var left = (Regex.IsMatch(incomingUrl, regex)) ? Regex.Match(incomingUrl, regex).Groups[1].Value : incomingUrl;
var right = (Regex.IsMatch(toMatchUrl, regex)) ? Regex.Match(toMatchUrl, regex).Groups[1].Value : toMatchUrl;
return left == right;
}
private GetRedirectUrlArgs CheckForDirectMatch(Database db, string requestedUrl, string requestedPath, GetRedirectUrlArgs args)
{
var isMediaRequest = requestedUrl.StartsWith("/-/media") || requestedPath.StartsWith("/-/media");
// Loop through the exact match entries to look for a match.
foreach (var possibleRedirect in RedirectRepository.GetRedirects(db, Constants.Templates.RedirectUrl, Constants.Templates.VersionedRedirectUrl, Sitecore.Configuration.Settings.GetSetting(Constants.Settings.QueryExactMatch)))
{
var redirectFromUrl = possibleRedirect[Constants.Fields.RequestedUrl];
if (isMediaRequest &&
(!IsMediaDirectMatch(requestedPath, redirectFromUrl)
&& !(Uri.IsWellFormedUriString(requestedUrl, UriKind.RelativeOrAbsolute)
&& Uri.TryCreate(requestedUrl, UriKind.RelativeOrAbsolute, out Uri requestedUri)
&& IsMediaDirectMatch(requestedUri.AbsolutePath, redirectFromUrl))))
{
continue;
}
else if (!isMediaRequest
&& !requestedUrl.Equals(redirectFromUrl, StringComparison.OrdinalIgnoreCase)
&& !requestedPath.Equals(redirectFromUrl, StringComparison.OrdinalIgnoreCase))
{
continue;
}
var redirectToItemId = possibleRedirect.Fields[Constants.Fields.RedirectToItem];
var redirectToUrl = possibleRedirect.Fields[Constants.Fields.RedirectToUrl];
if (redirectToItemId.HasValue && !string.IsNullOrEmpty(redirectToItemId.ToString()))
{
var redirectToItem = db.GetItem(ID.Parse(redirectToItemId));
if (redirectToItem == null)
{
continue;
}
var responseStatus = GetResponseStatus(possibleRedirect);
args.RedirectItem = redirectToItem;
args.RedirectStatusCode = responseStatus;
return args;
}
if (redirectToUrl.HasValue && !string.IsNullOrEmpty(redirectToUrl.ToString()))
{
var responseStatus = GetResponseStatus(possibleRedirect);
args.RedirectUrl = redirectToUrl.Value;
args.RedirectStatusCode = responseStatus;
return args;
}
}
return args;
}
private GetRedirectUrlArgs CheckForRegExMatch(Database db, string requestedUrl, string requestedPathAndQuery, GetRedirectUrlArgs args)
{
// find a match
foreach (var possibleRedirectPattern in RedirectRepository.GetRedirects(db, Constants.Templates.RedirectPattern, Constants.Templates.VersionedRedirectPattern, Sitecore.Configuration.Settings.GetSetting(Constants.Settings.QueryExactMatch)))
{
var redirectPath = string.Empty;
if (Regex.IsMatch(requestedUrl, possibleRedirectPattern[Constants.Fields.RequestedExpression], RegexOptions.IgnoreCase))
{
redirectPath = Regex.Replace(requestedUrl, possibleRedirectPattern[Constants.Fields.RequestedExpression],
possibleRedirectPattern[Constants.Fields.SourceItem], RegexOptions.IgnoreCase);
}
else if (Regex.IsMatch(requestedPathAndQuery, possibleRedirectPattern[Constants.Fields.RequestedExpression], RegexOptions.IgnoreCase))
{
redirectPath = Regex.Replace(requestedPathAndQuery,
possibleRedirectPattern[Constants.Fields.RequestedExpression],
possibleRedirectPattern[Constants.Fields.SourceItem], RegexOptions.IgnoreCase);
}
if (string.IsNullOrEmpty(redirectPath))
{
continue;
}
// Query portion gets in the way of getting the sitecore item.
var pathAndQuery = redirectPath.Split('?');
var path = pathAndQuery[0];
var redirectToItem = db.GetItem(path);
if (redirectToItem == null)
{
if (LinkManager.GetDefaultUrlOptions() != null && LinkManager.GetDefaultUrlOptions().EncodeNames)
{
path = Sitecore.MainUtil.DecodeName(path);
}
redirectToItem = db.GetItem(path);
}
if (redirectToItem != null)
{
var responseStatus = GetResponseStatus(possibleRedirectPattern);
args.RedirectStatusCode = responseStatus;
args.RedirectItem = redirectToItem;
return args;
}
}
return args;
}
private GetRedirectUrlArgs CheckForRulesMatch(Database db, string requestedUrl, string requestedPathAndQuery, GetRedirectUrlArgs args)
{
//pattern match items to find a match
foreach (var possibleRedirectRule in RedirectRepository.GetRedirects(db, Constants.Templates.RedirectRule, Constants.Templates.VersionedRedirectRule, Sitecore.Configuration.Settings.GetSetting(Constants.Settings.QueryExactMatch)))
{
var ruleContext = new RuleContext();
ruleContext.Parameters.Add("newUrl", requestedUrl);
foreach (var rule in RuleFactory.GetRules<RuleContext>((IEnumerable<Item>)new Item[1] { possibleRedirectRule }, "Redirect Rule").Rules)
{
if (rule.Condition == null)
{
continue;
}
var stack = new RuleStack();
rule.Condition.Evaluate(ruleContext, stack);
if (!ruleContext.IsAborted && (stack.Count != 0 && (bool)stack.Pop()))
{
foreach (var action in rule.Actions)
{
action.Apply(ruleContext);
}
}
}
if (ruleContext.Parameters["newUrl"] != null && ruleContext.Parameters["newUrl"].ToString() != string.Empty && ruleContext.Parameters["newUrl"].ToString() != requestedUrl)
{
var responseStatus = GetResponseStatus(possibleRedirectRule);
args.RedirectUrl = ruleContext.Parameters["newUrl"].ToString();
args.RedirectStatusCode = responseStatus;
return args;
}
}
return args;
}
private static ResponseStatus GetResponseStatus(Item redirectItem)
{
var result = new ResponseStatus
{
Status = "301 Moved Permanently",
StatusCode = 301,
};
var responseStatusCodeId = redirectItem?.Fields[Constants.Fields.ResponseStatusCode];
if (string.IsNullOrEmpty(responseStatusCodeId?.ToString())) return result;
var responseStatusCodeItem = redirectItem.Database.GetItem(ID.Parse(responseStatusCodeId));
if (responseStatusCodeItem != null)
{
result.Status = responseStatusCodeItem.Name;
result.StatusCode = responseStatusCodeItem.GetIntegerFieldValue(Constants.Fields.StatusCode, result.StatusCode);
}
return result;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment