Created
November 24, 2023 15:45
-
-
Save steliodibello/f849cd443471650ddcacbf3ad37d75d4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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