//TODO would want this for unit tests to be easily loaded from a collection... public virtual string GetSampleValue(string variable, RedirectData data) { if (LookupDictionary != null && LookupDictionary.ContainsKey(variable)) { return LookupDictionary[variable](data); } switch (variable) { case "HTTP_TRUE_CLIENT_IP": return GetRandom(IpExamples); case "HTTP_HOST": case "HTTP:Host": return data.OriginalUrl.Host; case "HTTP:User-Agent": return GetRandom(UserAgentExamples); case "REQUEST_METHOD": return "GET"; case "HTTPS": return data.OriginalUrl.OriginalString.StartsWith("https") ? "ON" : "OFF"; case "SERVER_PORT": return data.OriginalUrl.Port.ToString(); case "QUERY_STRING": return data.OriginalUrl.Query; case "HTTP:Referer": return GetRandom(ReferrerExamples); case "REQUEST_URI": return data.OriginalUrl.OriginalString; } throw new Exception("Unknown variable: " + variable); }
public bool ProcessConditions(ref RedirectData data) { //Default to true if (Conditions == null) { return(true); } foreach (var c in Conditions) { try { if (!c.MatchesCondition(ref data)) { return(false); } } catch (Exception ex) { throw new Exception("Failed processing condition from line: " + c.LineNumber, ex); } } //data.RuleSetMatched = this; return(true); }
public RedirectData ProcessRules(RedirectData data) { foreach (var rule in Rules) { try { data = rule.ProcessRule(data); switch (data.Status) { case RedirectStatus.NotProcessed: //case RedirectStatus.Continue: continue; case RedirectStatus.Modified: data.RuleSetMatched = this; continue; case RedirectStatus.Redirected: data.RuleSetMatched = this; break; default: throw new Exception("Unknown RedirectStatus... code needs to be updated: " + data.Status.ToString()); } } catch (Exception ex) { throw new Exception("Failed processing rule from line: " + rule.LineNumber, ex); } } return(data); }
public string BuildOutputUrl(RedirectData data) { var ruleMatches = data.RuleMatchGroups ?? new List<string>(); var conditionMatches = data.ConditionMatchGroups ?? new List<string>(); var processedUrl = Regex.Replace(ReplacePattern, @"(\$\d|%\d|\$\$\d\d|%%\d\d)", match => Evaluator(match, ruleMatches, conditionMatches)); return Options_PostProcessing(processedUrl); }
public string BuildOutputUrl(RedirectData data) { var ruleMatches = data.RuleMatchGroups ?? new List <string>(); var conditionMatches = data.ConditionMatchGroups ?? new List <string>(); var processedUrl = Regex.Replace(ReplacePattern, @"(\$\d|%\d|\$\$\d\d|%%\d\d)", match => Evaluator(match, ruleMatches, conditionMatches)); return(Options_PostProcessing(processedUrl)); }
//TODO all these tests could be moved into this... public static void BuildAndTestConditions(IEnumerable<string> lines, string originalUrl, bool matchesCond, bool matchesRule, string expectedUrl, int? expectedRuleCount = null) { var samples = new RandomSampleValues(); var factory = new RewriteFactory(samples); var lineNum = 1; var redirects = lines.Select(l => factory.Build(lineNum++, l)); var ruleSet = RewriteRuleSet.BuildRuleSets(redirects); var redirectData = new RedirectData(originalUrl); TestConditions(matchesCond, matchesRule, null, expectedUrl, ruleSet, redirectData); }
public bool MatchesCondition(ref RedirectData data) { string testString = data.OriginalUrl.PathAndQuery; if (Variable != null) testString = _values.GetSampleValue(Variable, data); var m = Regex.Match(testString, MatchPattern); if (m.Success) { data.ConditionMatchGroups = m.Groups.Cast<Group>() .Select(a => a.Value).ToList(); } return m.Success; }
public RedirectData TestUrl(string url) { if (RulesSets == null) throw new Exception("Did you forget to call LoadConfig?"); var data = new RedirectData(url); var matchesRuleSets = RulesSets.Where(r => r.ProcessConditions(ref data)); foreach (var rule in matchesRuleSets) { data = rule.ProcessRules(data); if (data.Status == RedirectStatus.Redirected) break; } return data; }
public bool MatchesCondition(ref RedirectData data) { string testString = data.OriginalUrl.PathAndQuery; if (Variable != null) { testString = _values.GetSampleValue(Variable, data); } var m = Regex.Match(testString, MatchPattern); if (m.Success) { data.ConditionMatchGroups = m.Groups.Cast <Group>() .Select(a => a.Value).ToList(); } return(m.Success); }
public bool ProcessConditions(ref RedirectData data) { //Default to true if (Conditions == null) return true; foreach (var c in Conditions) { try { if (!c.MatchesCondition(ref data)) return false; } catch (Exception ex) { throw new Exception("Failed processing condition from line: " + c.LineNumber, ex); } } //data.RuleSetMatched = this; return true; }
public void Https_test_cases(string originalUrl, bool matchesCond, bool matchesRule, string expectedUrl) { //Arrange var samples = new RandomSampleValues(); var factory = new RewriteFactory(samples); string[] lines = { @"# Force SSL for pages that request personally-identifiable information", @"RewriteCond %{HTTPS} ^(?!on).*$", @"RewriteCond %{SERVER_PORT} ^80$", @"RewriteCond %{HTTP:Host} (.*)", @"RewriteRule ^(/ltl-freight)(.*)$ https\://%1$1 [NC,R=301]", }; var lineNum = 1; var redirects = lines.Select(l => factory.Build(lineNum++, l)); var ruleSet = RewriteRuleSet.BuildRuleSets(redirects); var redirectData = new RedirectData(originalUrl); TestConditions(matchesCond, matchesRule, 1, expectedUrl, ruleSet, redirectData); }
public RedirectData ProcessRule(RedirectData data) { //TODO actually this is the OriginalString when condition checks that... or something //WTF am i saying above... i think i want ProcessedUrl since that will default back to Original if not changed (i.e. its "CurrentUrl") var m = Regex.Match(data.CurrentPathAndQuery, MatchPattern, Options_Regex()); if (m.Success) { data.RuleMatchGroups = m.Groups.Cast <Group>() .Select(a => a.Value).ToList(); data.ProcessedUrl = BuildOutputUrl(data); if ((Options & RuleOptions.FINISHED) > 0 && data.OriginalUrl.OriginalString != data.ProcessedUrl) { data.Status = RedirectStatus.Redirected; data.SetUrlChanged(); } else if (data.OriginalUrl.OriginalString != data.ProcessedUrl) { data.Status = RedirectStatus.Modified; data.SetUrlChanged(); } else { //Is this CURRENT status? - yes data.Status = RedirectStatus.NotProcessed; } } else { //Is this CURRENT status? - yes data.Status = RedirectStatus.NotProcessed; } return(data); }
public RedirectData ProcessRule(RedirectData data) { //TODO actually this is the OriginalString when condition checks that... or something //WTF am i saying above... i think i want ProcessedUrl since that will default back to Original if not changed (i.e. its "CurrentUrl") var m = Regex.Match(data.CurrentPathAndQuery, MatchPattern, Options_Regex()); if (m.Success) { data.RuleMatchGroups = m.Groups.Cast<Group>() .Select(a => a.Value).ToList(); data.ProcessedUrl = BuildOutputUrl(data); if ((Options & RuleOptions.FINISHED) > 0 && data.OriginalUrl.OriginalString != data.ProcessedUrl) { data.Status = RedirectStatus.Redirected; data.SetUrlChanged(); } else if (data.OriginalUrl.OriginalString != data.ProcessedUrl) { data.Status = RedirectStatus.Modified; data.SetUrlChanged(); } else { //Is this CURRENT status? - yes data.Status = RedirectStatus.NotProcessed; } } else { //Is this CURRENT status? - yes data.Status = RedirectStatus.NotProcessed; } return data; }
public void Pricing_index_page_urls(string originalUrl, bool matchesCond, bool matchesRule, string expectedUrl) { //Arrange var samples = new RandomSampleValues(); var factory = new RewriteFactory(samples); string[] lines = { @"RewriteCond %{HTTP:Host} ^directory[2]?\.uship\.com$", @"RewriteRule ^/tips/showtip.aspx(.*)$ http://www.uship.com/tips/showtip.aspx$1 [NC,R=301]", @"", @"# ...", @"", @"# Listing Index", @"RewriteRule ^/pricing/((?:[a-z]|[-])+)/((?:[a-z]|[-])+)(?:/page/([0-9]+))? /listingindex/PricingCommodity.aspx?c=$1&c2=$2&page=$3 [NC,L]", @"RewriteRule ^/pricing/((?:[a-z]|[-])+)(?:/page/([0-9]+))? /listingindex/PricingCommodity.aspx?c=$1&page=$2 [NC,L]", @"RewriteRule ^/pricing/?$ /listingindex/?c=4&c2=79 [NC,L]" }; var lineNum = 1; var redirects = lines.Select(l => factory.Build(lineNum++, l)); var ruleSet = RewriteRuleSet.BuildRuleSets(redirects); var redirectData = new RedirectData(originalUrl); TestConditions(matchesCond, matchesRule, 3, expectedUrl, ruleSet, redirectData); }
public void Single_ruleset_should_manually_work_as_expected(string originalUrl, bool matchesCond, bool matchesRule, string expectedUrl) { //Arrange //TODO use structure map for getting the instance???: var samples = new RandomSampleValues(); var factory = new RewriteFactory(samples); string[] lines = { @"RewriteCond %{HTTP:Host} ^(movers|household-goods|vehicles|boats|motorcycles|special-care|freight|pets-livestock|food-agriculture|junk|craigslist)[2]?\.uship\.com$", @"RewriteRule ^(?!.+\.axd|.+\.ashx|public/images|sticky/images)/([^?]*\u.*)/?(?:[^?]*\u.*)?$ /$1 [CL,R=301]" }; var redirectData = new RedirectData(originalUrl); //Act var lineNum = 1; var redirects = lines.Select(l => factory.Build(lineNum++, l)); //Assert var redirectLines = redirects as IList<IRedirectLine> ?? redirects.ToList(); redirectLines.Count().Should().Be(2); var cond = (RewriteCondition) redirectLines.Single(x => x.LineType == RedirectLineType.Condition); cond.Variable.Should().Be("HTTP:Host"); cond.MatchesCondition(ref redirectData).Should().Be(matchesCond); if (matchesCond) { var rule = (RewriteRule) redirectLines.Single(x => x.LineType == RedirectLineType.Rule); redirectData = rule.ProcessRule(redirectData); if (matchesRule) { redirectData.Status.Should().NotBe(RedirectStatus.NotProcessed); redirectData.ProcessedUrl.Should().Be(expectedUrl); } else { redirectData.Status.Should().Be(RedirectStatus.NotProcessed); } } }
public void Single_ruleset_should_object_work_as_expected(string originalUrl, bool matchesCond, bool matchesRule, string expectedUrl) { //Arrange var samples = new RandomSampleValues(); var factory = new RewriteFactory(samples); string[] lines = { @"RewriteCond %{HTTP:Host} ^(movers|household-goods|vehicles|boats|motorcycles|special-care|freight|pets-livestock|food-agriculture|junk|craigslist)[2]?\.uship\.com$", @"RewriteRule ^(?!.+\.axd|.+\.ashx|public/images|sticky/images)/([^?]*\u.*)/?(?:[^?]*\u.*)?$ /$1 [CL,R=301]" }; var lineNum = 1; var redirects = lines.Select(l => factory.Build(lineNum++, l)); var ruleSet = RewriteRuleSet.BuildRuleSets(redirects); var redirectData = new RedirectData(originalUrl); TestConditions(matchesCond, matchesRule, 1, expectedUrl, ruleSet, redirectData); }
private static void TestConditions(bool matchesCond, bool matchesRule, int? expectedRuleCount, string expectedUrl, IEnumerable<RewriteRuleSet> ruleSet, RedirectData redirectData) { //Act var matchingSets = ruleSet.Where(r => r.ProcessConditions(ref redirectData)); var rewriteRuleSets = matchingSets as IList<RewriteRuleSet> ?? matchingSets.ToList(); //Assert if (matchesCond) { if (expectedRuleCount != null) rewriteRuleSets.Count().Should().Be(expectedRuleCount); //TODO this should be a method on RewriteRuleSetCollection... foreach (var rs in rewriteRuleSets) { redirectData = rs.ProcessRules(redirectData); if (redirectData.Status == RedirectStatus.Redirected) break; } if (matchesRule) { //TODO add an option for LAST RULE too? //redirectData.Status.Should().NotBe(RedirectStatus.NotProcessed); redirectData.WasRedirected.Should().BeTrue("Was NOT processed when it should have been"); redirectData.ProcessedUrl.Should().Be(expectedUrl); } else { //redirectData.Status.Should().Be(RedirectStatus.NotProcessed); redirectData.WasRedirected.Should().BeFalse("Was processed when it should NOT have been"); if (expectedUrl != null) redirectData.ProcessedUrl.Should().Be(expectedUrl); } } else { rewriteRuleSets.Count().Should().Be(0); } }
public void Vortal_rewrites_alone_should_go_to_correct_domain(string originalUrl, bool matchesCond, bool matchesRule, string expectedUrl) { //Arrange var samples = new RandomSampleValues(); var factory = new RewriteFactory(samples); string[] lines = { @"RewriteCond %{HTTP:Host} ^(movers|vehicles|boats|motorcycles|freight)\.uship\.com$", @"RewriteRule ^/(.+)$ http://www.uship.com/%1/$1 [CL,NC,R=301]", @"", @"RewriteCond %{HTTP:Host} ^pets-livestock\.uship\.com$", @"RewriteRule ^/(.+)$ http://www.uship.com/pet-shipping/$1 [CL,NC,R=301]", @"", @"RewriteCond %{HTTP:Host} ^household-goods\.uship\.com$", @"RewriteRule ^/(.+)$ http://www.uship.com/furniture/$1 [CL,NC,R=301]", @"", @"# 301 these lortals to their vortals, these lortals will not exist", @"RewriteCond %{HTTP:Host} ^(craigslist|special-care|junk|food)(?:-agriculture)?\.uship\.com$", @"RewriteRule ^/(.+)$ http://www.uship.com/%1/ [CL,NC,R=301]" }; var lineNum = 1; var redirects = lines.Select(l => factory.Build(lineNum++, l)); var ruleSet = RewriteRuleSet.BuildRuleSets(redirects); var redirectData = new RedirectData(originalUrl); TestConditions(matchesCond, matchesRule, 1, expectedUrl, ruleSet, redirectData); }
public RedirectData ProcessRules(RedirectData data) { foreach (var rule in Rules) { try { data = rule.ProcessRule(data); switch (data.Status) { case RedirectStatus.NotProcessed: //case RedirectStatus.Continue: continue; case RedirectStatus.Modified: data.RuleSetMatched = this; continue; case RedirectStatus.Redirected: data.RuleSetMatched = this; break; default: throw new Exception("Unknown RedirectStatus... code needs to be updated: " + data.Status.ToString()); } } catch (Exception ex) { throw new Exception("Failed processing rule from line: " + rule.LineNumber, ex); } } return data; }