diff --git a/BasicMiddleware.sln b/BasicMiddleware.sln
index a431cdab18..dd15eee89b 100644
--- a/BasicMiddleware.sln
+++ b/BasicMiddleware.sln
@@ -5,6 +5,9 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.HttpOverrides", "src\Microsoft.AspNetCore.HttpOverrides\Microsoft.AspNetCore.HttpOverrides.xproj", "{517308C3-B477-4B01-B461-CAB9C10B6928}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A5076D28-FA7E-4606-9410-FEDD0D603527}"
+ ProjectSection(SolutionItems) = preProject
+ global.json = global.json
+ EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8437B0F3-3894-4828-A945-A9187F37631D}"
EndProject
diff --git a/samples/RewriteSample/Startup.cs b/samples/RewriteSample/Startup.cs
index 5fe6a3840c..b83d5677e7 100644
--- a/samples/RewriteSample/Startup.cs
+++ b/samples/RewriteSample/Startup.cs
@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Rewrite;
+using Microsoft.AspNetCore.Rewrite.Internal;
namespace RewriteSample
{
@@ -13,9 +14,29 @@ namespace RewriteSample
{
public void Configure(IApplicationBuilder app, IHostingEnvironment hostingEnv)
{
+ // Four main use cases for Rewrite Options.
+ // 1. Importing from a UrlRewrite file, which are IIS Rewrite rules.
+ // This file is in xml format, starting with the tag.
+ // 2. Importing from a mod_rewrite file, which are mod_rewrite rules.
+ // This file is in standard mod_rewrite format which only contains rewrite information.
+ // 3. Inline rules in code, where you can specify rules such as rewrites and redirects
+ // based on certain conditions. Ex: RedirectToHttps will check if the request is https,
+ // else it will redirect the request with https.
+ // 4. Functional rules. If a user has a very specific function they would like to implement
+ // (ex StringReplace) that are easy to implement in code, they can do so by calling
+ // AddFunctionalRule(Func);
+ // TODO make this startup do something useful.
app.UseRewriter(new RewriteOptions()
.ImportFromUrlRewrite(hostingEnv, "UrlRewrite.xml")
- .ImportFromModRewrite(hostingEnv, "Rewrite.txt"));
+ .ImportFromModRewrite(hostingEnv, "Rewrite.txt")
+ .RedirectToHttps(StatusCodes.Status307TemporaryRedirect)
+ .RewriteRule("/foo/(.*)/bar", "{R:1}/bar")
+ .AddRule(ctx =>
+ {
+ ctx.HttpContext.Request.Path = "/index";
+ return RuleResult.Continue;
+ }));
+
app.Run(context => context.Response.WriteAsync(context.Request.Path));
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/CodeRewriteExtensions.cs b/src/Microsoft.AspNetCore.Rewrite/CodeRewriteExtensions.cs
index 51060ebdfc..9da5101c96 100644
--- a/src/Microsoft.AspNetCore.Rewrite/CodeRewriteExtensions.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/CodeRewriteExtensions.cs
@@ -3,8 +3,9 @@
using System;
using System.Collections.Generic;
-using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Rewrite.Internal;
+using Microsoft.AspNetCore.Rewrite.Internal.CodeRules;
+using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite;
namespace Microsoft.AspNetCore.Rewrite
{
@@ -35,69 +36,69 @@ namespace Microsoft.AspNetCore.Rewrite
return options;
}
- ///
- /// Creates a rewrite path rule.
- ///
- /// The Url rewrite options.
- /// The string regex pattern to compare against the http context.
- /// The string to replace the path with (with capture parameters).
- /// Whether or not to stop rewriting on success of rule.
- ///
- public static RewriteOptions RewritePath(this RewriteOptions options, string regex, string newPath, bool stopRewriteOnSuccess = false)
+ public static RewriteOptions RewriteRule(this RewriteOptions options, string regex, string onMatch)
{
- options.Rules.Add(new PathRule { MatchPattern = new Regex(regex, RegexOptions.Compiled, TimeSpan.FromMilliseconds(1)), OnMatch = newPath, OnCompletion = stopRewriteOnSuccess ? Transformation.TerminatingRewrite : Transformation.Rewrite });
+ return RewriteRule(options, regex, onMatch, stopProcessing: false);
+ }
+
+ public static RewriteOptions RewriteRule(this RewriteOptions options, string regex, string onMatch, bool stopProcessing)
+ {
+ var builder = new UrlRewriteRuleBuilder();
+ var pattern = InputParser.ParseInputString(onMatch);
+
+ builder.AddUrlMatch(regex);
+ builder.AddUrlAction(pattern, actionType: ActionType.Rewrite, stopProcessing: stopProcessing);
+ options.Rules.Add(builder.Build());
return options;
}
- ///
- /// Rewrite http to https.
- ///
- /// The Url rewrite options.
- /// Whether or not to stop rewriting on success of rule.
- ///
- public static RewriteOptions RewriteScheme(this RewriteOptions options, bool stopRewriteOnSuccess = false)
+ public static RewriteOptions RedirectRule(this RewriteOptions options, string regex, string onMatch, int statusCode)
{
- options.Rules.Add(new SchemeRule {OnCompletion = stopRewriteOnSuccess ? Transformation.TerminatingRewrite : Transformation.Rewrite });
+ return RedirectRule(options, regex, onMatch, statusCode, stopProcessing: false);
+ }
+
+ public static RewriteOptions RedirectRule(this RewriteOptions options, string regex, string onMatch, int statusCode, bool stopProcessing)
+ {
+ var builder = new UrlRewriteRuleBuilder();
+ var pattern = InputParser.ParseInputString(onMatch);
+
+ builder.AddUrlMatch(regex);
+ builder.AddUrlAction(pattern, actionType: ActionType.Redirect, stopProcessing: stopProcessing);
+ options.Rules.Add(builder.Build());
return options;
}
- ///
- /// Redirect a path to another path.
- ///
- /// The Url rewrite options.
- /// The string regex pattern to compare against the http context.
- /// The string to replace the path with (with capture parameters).
- /// Whether or not to stop rewriting on success of rule.
- ///
- public static RewriteOptions RedirectPath(this RewriteOptions options, string regex, string newPath, bool stopRewriteOnSuccess = false)
+ public static RewriteOptions RedirectToHttps(this RewriteOptions options, int statusCode)
{
- options.Rules.Add(new PathRule { MatchPattern = new Regex(regex, RegexOptions.Compiled, TimeSpan.FromMilliseconds(1)), OnMatch = newPath, OnCompletion = Transformation.Redirect });
+ return RedirectToHttps(options, statusCode, null);
+ }
+
+ // TODO Don't do this, it doesn't work in all cases. Will refactor tonight/ tomorrow.
+ public static RewriteOptions RedirectToHttps(this RewriteOptions options, int statusCode, int? sslPort)
+ {
+ options.Rules.Add(new RedirectToHttpsRule { StatusCode = statusCode, SSLPort = sslPort });
return options;
}
- ///
- /// Redirect http to https.
- ///
- /// The Url rewrite options.
- /// The port to redirect the scheme to.
- ///
- public static RewriteOptions RedirectScheme(this RewriteOptions options, int? sslPort)
+ public static RewriteOptions RewriteToHttps(this RewriteOptions options)
+ {
+ return RewriteToHttps(options, sslPort: null, stopProcessing: false);
+ }
+
+ public static RewriteOptions RewriteToHttps(this RewriteOptions options, int? sslPort)
{
- options.Rules.Add(new SchemeRule { SSLPort = sslPort, OnCompletion = Transformation.Redirect });
+ return RewriteToHttps(options, sslPort, stopProcessing: false);
+ }
+
+ public static RewriteOptions RewriteToHttps(this RewriteOptions options, int? sslPort, bool stopProcessing)
+ {
+ options.Rules.Add(new RewriteToHttpsRule {SSLPort = sslPort, stopProcessing = stopProcessing });
return options;
}
- ///
- /// User generated rule to do a specific match on a path and what to do on success of the match.
- ///
- ///
- ///
- ///
- ///
- ///
- public static RewriteOptions CustomRule(this RewriteOptions options, Func onApplyRule, Transformation transform, string description = null)
+ public static RewriteOptions AddRule(this RewriteOptions options, Func rule)
{
- options.Rules.Add(new FunctionalRule { OnApplyRule = onApplyRule, OnCompletion = transform});
+ options.Rules.Add(new FunctionalRule { OnApplyRule = rule});
return options;
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/FunctionalRule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/FunctionalRule.cs
similarity index 75%
rename from src/Microsoft.AspNetCore.Rewrite/Internal/FunctionalRule.cs
rename to src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/FunctionalRule.cs
index 5704a23a40..eccf9e735f 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/FunctionalRule.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/FunctionalRule.cs
@@ -3,12 +3,11 @@
using System;
-namespace Microsoft.AspNetCore.Rewrite.Internal
+namespace Microsoft.AspNetCore.Rewrite.Internal.CodeRules
{
public class FunctionalRule : Rule
{
public Func OnApplyRule { get; set; }
- public Transformation OnCompletion { get; set; } = Transformation.Rewrite;
public override RuleResult ApplyRule(RewriteContext context) => OnApplyRule(context);
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/SchemeRule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/RedirectToHttpsRule.cs
similarity index 65%
rename from src/Microsoft.AspNetCore.Rewrite/Internal/SchemeRule.cs
rename to src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/RedirectToHttpsRule.cs
index 87a08544e8..3dd9d6df39 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/SchemeRule.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/RedirectToHttpsRule.cs
@@ -4,12 +4,12 @@
using System.Text;
using Microsoft.AspNetCore.Http;
-namespace Microsoft.AspNetCore.Rewrite.Internal
+namespace Microsoft.AspNetCore.Rewrite.Internal.CodeRules
{
- public class SchemeRule : Rule
+ public class RedirectToHttpsRule : Rule
{
public int? SSLPort { get; set; }
- public Transformation OnCompletion { get; set; } = Transformation.Rewrite;
+ public int StatusCode { get; set; }
public override RuleResult ApplyRule(RewriteContext context)
{
@@ -28,20 +28,6 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
host = new HostString(host.Host);
}
- if ((OnCompletion != Transformation.Redirect))
- {
- context.HttpContext.Request.Scheme = "https";
- context.HttpContext.Request.Host = host;
- if (OnCompletion == Transformation.TerminatingRewrite)
- {
- return RuleResult.StopRules;
- }
- else
- {
- return RuleResult.Continue;
- }
- }
-
var req = context.HttpContext.Request;
var newUrl = new StringBuilder().Append("https://").Append(host).Append(req.PathBase).Append(req.Path).Append(req.QueryString);
@@ -51,4 +37,4 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
return RuleResult.Continue;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/RewriteToHttpsRule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/RewriteToHttpsRule.cs
new file mode 100644
index 0000000000..cccb76e6d1
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/RewriteToHttpsRule.cs
@@ -0,0 +1,42 @@
+
+using Microsoft.AspNetCore.Http;
+
+namespace Microsoft.AspNetCore.Rewrite.Internal.CodeRules
+{
+ public class RewriteToHttpsRule : Rule
+ {
+
+ public bool stopProcessing { get; set; }
+ public int? SSLPort { get; set; }
+ public override RuleResult ApplyRule(RewriteContext context)
+ {
+ // TODO this only does http to https, add more features in the future.
+ if (!context.HttpContext.Request.IsHttps)
+ {
+ var host = context.HttpContext.Request.Host;
+ if (SSLPort.HasValue && SSLPort.Value > 0)
+ {
+ // a specific SSL port is specified
+ host = new HostString(host.Host, SSLPort.Value);
+ }
+ else
+ {
+ // clear the port
+ host = new HostString(host.Host);
+ }
+
+ context.HttpContext.Request.Scheme = "https";
+ context.HttpContext.Request.Host = host;
+ if (stopProcessing)
+ {
+ return RuleResult.StopRules;
+ }
+ else
+ {
+ return RuleResult.Continue;
+ }
+ }
+ return RuleResult.Continue;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/RuleExpression.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleExpression.cs
similarity index 86%
rename from src/Microsoft.AspNetCore.Rewrite/Internal/RuleExpression.cs
rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleExpression.cs
index 52458cc542..1c29b18f0e 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/RuleExpression.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleExpression.cs
@@ -3,7 +3,7 @@
using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands;
-namespace Microsoft.AspNetCore.Rewrite.Internal
+namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
{
public class RuleExpression
{
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/PathRule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/PathRule.cs
deleted file mode 100644
index 88b07e6cde..0000000000
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/PathRule.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System.Text.RegularExpressions;
-
-namespace Microsoft.AspNetCore.Rewrite.Internal
-{
- public class PathRule : Rule
- {
- public Regex MatchPattern { get; set; }
- public string OnMatch { get; set; }
- public Transformation OnCompletion { get; set; } = Transformation.Rewrite;
- public override RuleResult ApplyRule(RewriteContext context)
- {
- var matches = MatchPattern.Match(context.HttpContext.Request.Path);
- if (matches.Success)
- {
- // New method here to translate the outgoing format string to the correct value.
- var path = matches.Result(OnMatch);
- if (OnCompletion == Transformation.Redirect)
- {
- var req = context.HttpContext.Request;
- var newUrl = string.Concat(
- req.Scheme,
- "://",
- req.PathBase,
- path,
- req.QueryString);
- context.HttpContext.Response.Redirect(newUrl);
- return RuleResult.ResponseComplete;
- }
- else
- {
- context.HttpContext.Request.Path = path;
- }
- if (OnCompletion == Transformation.TerminatingRewrite)
- {
- return RuleResult.StopRules;
- }
- else
- {
- return RuleResult.Continue;
- }
- }
- return RuleResult.Continue;
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/Transformation.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/Transformation.cs
deleted file mode 100644
index 01ca2dc9cf..0000000000
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/Transformation.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-namespace Microsoft.AspNetCore.Rewrite.Internal
-{
- public enum Transformation
- {
- Rewrite,
- Redirect,
- TerminatingRewrite
- }
-}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedCondition.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedCondition.cs
deleted file mode 100644
index e34ccdb00f..0000000000
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedCondition.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
-{
- public class ParsedCondition
- {
- public bool Negate { get; set; }
- public bool IgnoreCase { get; set; } = true;
- public MatchType MatchType { get; set; } = MatchType.Pattern;
- }
-}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedUrlAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedUrlAction.cs
deleted file mode 100644
index 857c2f16cd..0000000000
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedUrlAction.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
-{
- public class ParsedUrlAction
- {
- public ActionType Type { get; set; }
- public Pattern Url { get; set; }
- public bool AppendQueryString { get; set; } = true;
- public bool LogRewrittenUrl { get; set; } // Ignoring this flag.
- public RedirectType RedirectType { get; set; } = RedirectType.Permanent;
- }
-}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedUrlMatch.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedUrlMatch.cs
deleted file mode 100644
index 9f183fadc3..0000000000
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedUrlMatch.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
-{
- public class ParsedUrlMatch
- {
- public bool IgnoreCase { get; set; }
- public bool Negate { get; set; }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/RewriteTags.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/RewriteTags.cs
index 16074abfb3..2421fe2eb5 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/RewriteTags.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/RewriteTags.cs
@@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
public const string Input = "input";
public const string Pattern = "pattern";
public const string Type = "type";
- public const string AppendQuery = "appendQueryString";
+ public const string AppendQueryString = "appendQueryString";
public const string LogRewrittenUrl = "logRewrittenUrl";
public const string RedirectType = "redirectType";
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlAction.cs
index 404561b25b..489f4a6b53 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlAction.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlAction.cs
@@ -8,7 +8,6 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
public abstract class UrlAction
{
public Pattern Url { get; set; }
-
public abstract RuleResult ApplyAction(HttpContext context, MatchResults ruleMatch, MatchResults condMatch);
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteFileParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteFileParser.cs
index 350e697b24..4f9e0bbc22 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteFileParser.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteFileParser.cs
@@ -5,11 +5,8 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
-using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlActions;
-using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlMatches;
namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
{
@@ -27,14 +24,14 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
var result = new List();
// TODO Global rules are currently not treated differently than normal rules, fix.
// See: https://github.com/aspnet/BasicMiddleware/issues/59
- ParseRules(xmlRoot.Descendants(RewriteTags.GlobalRules).FirstOrDefault(), result, isGlobalRule: true);
- ParseRules(xmlRoot.Descendants(RewriteTags.Rules).FirstOrDefault(), result, isGlobalRule: false);
+ ParseRules(xmlRoot.Descendants(RewriteTags.GlobalRules).FirstOrDefault(), result);
+ ParseRules(xmlRoot.Descendants(RewriteTags.Rules).FirstOrDefault(), result);
return result;
}
return null;
}
- private static void ParseRules(XElement rules, List result, bool isGlobalRule)
+ private static void ParseRules(XElement rules, List result)
{
if (rules == null)
{
@@ -43,297 +40,176 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
foreach (var rule in rules.Elements(RewriteTags.Rule))
{
- var res = new UrlRewriteRule();
- SetRuleAttributes(rule, res);
- var action = rule.Element(RewriteTags.Action);
- if (action == null)
+ var builder = new UrlRewriteRuleBuilder();
+ ParseRuleAttributes(rule, builder);
+
+ if (builder.Enabled)
{
- ThrowUrlFormatException(rule, "Rule does not have an associated action attribute");
- }
- CreateUrlAction(action, res, isGlobalRule);
- if (res.Enabled)
- {
- result.Add(res);
+ result.Add(builder.Build());
}
}
}
- private static void SetRuleAttributes(XElement rule, UrlRewriteRule res)
+ private static void ParseRuleAttributes(XElement rule, UrlRewriteRuleBuilder builder)
{
-
- res.Name = rule.Attribute(RewriteTags.Name)?.Value;
+ builder.Name = rule.Attribute(RewriteTags.Name)?.Value;
bool enabled;
- if (bool.TryParse(rule.Attribute(RewriteTags.Enabled)?.Value, out enabled))
+ if (!bool.TryParse(rule.Attribute(RewriteTags.Enabled)?.Value, out enabled))
{
- res.Enabled = enabled;
+ builder.Enabled = true;
}
PatternSyntax patternSyntax;
- if (Enum.TryParse(rule.Attribute(RewriteTags.PatternSyntax)?.Value, out patternSyntax))
+ if (!Enum.TryParse(rule.Attribute(RewriteTags.PatternSyntax)?.Value, out patternSyntax))
{
- res.PatternSyntax = patternSyntax;
+ patternSyntax = PatternSyntax.ECMAScript;
}
bool stopProcessing;
- if (bool.TryParse(rule.Attribute(RewriteTags.StopProcessing)?.Value, out stopProcessing))
+ if (!bool.TryParse(rule.Attribute(RewriteTags.StopProcessing)?.Value, out stopProcessing))
{
- res.StopProcessing = stopProcessing;
+ stopProcessing = false;
}
+
var match = rule.Element(RewriteTags.Match);
if (match == null)
{
ThrowUrlFormatException(rule, "Cannot have rule without match");
}
- CreateMatch(match, res);
- CreateConditions(rule.Element(RewriteTags.Conditions), res);
+
+ var action = rule.Element(RewriteTags.Action);
+ if (action == null)
+ {
+ ThrowUrlFormatException(rule, "Rule does not have an associated action attribute");
+ }
+
+ ParseMatch(match, builder, patternSyntax);
+ ParseConditions(rule.Element(RewriteTags.Conditions), builder, patternSyntax);
+ ParseUrlAction(action, builder, stopProcessing);
}
- private static void CreateMatch(XElement match, UrlRewriteRule res)
+ private static void ParseMatch(XElement match, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)
{
- var matchRes = new ParsedUrlMatch();
-
- bool parBool;
- if (bool.TryParse(match.Attribute(RewriteTags.IgnoreCase)?.Value, out parBool))
- {
- matchRes.IgnoreCase = parBool;
- }
-
- if (bool.TryParse(match.Attribute(RewriteTags.Negate)?.Value, out parBool))
- {
- matchRes.Negate = parBool;
- }
-
var parsedInputString = match.Attribute(RewriteTags.Url)?.Value;
if (parsedInputString == null)
{
ThrowUrlFormatException(match, "Match must have Url Attribute");
}
- switch (res.PatternSyntax)
+ bool ignoreCase;
+ if (!bool.TryParse(match.Attribute(RewriteTags.IgnoreCase)?.Value, out ignoreCase))
{
- case PatternSyntax.ECMAScript:
- {
- if (matchRes.IgnoreCase)
- {
- var regex = new Regex(parsedInputString, RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout);
- res.InitialMatch = new RegexMatch(regex, matchRes.Negate);
- }
- else
- {
- var regex = new Regex(parsedInputString, RegexOptions.Compiled, RegexTimeout);
- res.InitialMatch = new RegexMatch(regex, matchRes.Negate);
- }
- }
- break;
- case PatternSyntax.WildCard:
- throw new NotImplementedException("Wildcard syntax is not supported.");
- case PatternSyntax.ExactMatch:
- res.InitialMatch = new ExactMatch(matchRes.IgnoreCase, parsedInputString, matchRes.Negate);
- break;
+ ignoreCase = true; // default
}
+
+ bool negate;
+ if (!bool.TryParse(match.Attribute(RewriteTags.Negate)?.Value, out negate))
+ {
+ negate = false;
+ }
+ builder.AddUrlMatch(parsedInputString, ignoreCase, negate, patternSyntax);
}
- private static void CreateConditions(XElement conditions, UrlRewriteRule res)
+
+
+ private static void ParseConditions(XElement conditions, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)
{
- // This is to avoid nullptr exception on referencing conditions.
- res.Conditions = new Conditions();
if (conditions == null)
{
return;
}
LogicalGrouping grouping;
- if (Enum.TryParse(conditions.Attribute(RewriteTags.MatchType)?.Value, out grouping))
+ if (!Enum.TryParse(conditions.Attribute(RewriteTags.MatchType)?.Value, out grouping))
{
- res.Conditions.MatchType = grouping;
+ grouping = LogicalGrouping.MatchAll;
}
- bool parBool;
- if (bool.TryParse(conditions.Attribute(RewriteTags.TrackingAllCaptures)?.Value, out parBool))
+ bool trackingAllCaptures;
+ if (!bool.TryParse(conditions.Attribute(RewriteTags.TrackingAllCaptures)?.Value, out trackingAllCaptures))
{
- res.Conditions.TrackingAllCaptures = parBool;
+ trackingAllCaptures = false;
}
+ builder.AddUrlConditions(grouping, trackingAllCaptures);
+
foreach (var cond in conditions.Elements(RewriteTags.Add))
{
- CreateCondition(cond, res);
+ ParseCondition(cond, builder, patternSyntax);
}
}
- private static void CreateCondition(XElement condition, UrlRewriteRule res)
+ private static void ParseCondition(XElement condition, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)
{
- var parsedCondRes = new ParsedCondition();
-
- bool parBool;
- if (bool.TryParse(condition.Attribute(RewriteTags.IgnoreCase)?.Value, out parBool))
+ bool ignoreCase;
+ if (!bool.TryParse(condition.Attribute(RewriteTags.IgnoreCase)?.Value, out ignoreCase))
{
- parsedCondRes.IgnoreCase = parBool;
+ ignoreCase = true;
}
- if (bool.TryParse(condition.Attribute(RewriteTags.Negate)?.Value, out parBool))
+ bool negate;
+ if (!bool.TryParse(condition.Attribute(RewriteTags.Negate)?.Value, out negate))
{
- parsedCondRes.Negate = parBool;
+ ignoreCase = false;
}
MatchType matchType;
- if (Enum.TryParse(condition.Attribute(RewriteTags.MatchType)?.Value, out matchType))
+ if (!Enum.TryParse(condition.Attribute(RewriteTags.MatchType)?.Value, out matchType))
{
- parsedCondRes.MatchType = matchType;
+ matchType = MatchType.Pattern;
}
- var parsedString = condition.Attribute(RewriteTags.Input)?.Value;
- if (parsedString == null)
+ var parsedInputString = condition.Attribute(RewriteTags.Input)?.Value;
+ if (parsedInputString == null)
{
ThrowUrlFormatException(condition, "Conditions must have an input attribute");
}
+ var parsedPatternString = condition.Attribute(RewriteTags.Pattern)?.Value;
+
Pattern input = null;
try
{
- input = InputParser.ParseInputString(parsedString);
+ input = InputParser.ParseInputString(parsedInputString);
+ builder.AddUrlCondition(input, parsedPatternString, patternSyntax, matchType, ignoreCase, negate);
+
}
catch (FormatException formatException)
{
ThrowUrlFormatException(condition, formatException.Message, formatException);
}
-
- switch (res.PatternSyntax)
- {
- case PatternSyntax.ECMAScript:
- {
- switch (parsedCondRes.MatchType)
- {
- case MatchType.Pattern:
- {
- parsedString = condition.Attribute(RewriteTags.Pattern)?.Value;
- if (parsedString == null)
- {
- ThrowUrlFormatException(condition, "Match does not have an associated pattern attribute in condition");
-
- }
- Regex regex = null;
-
- if (parsedCondRes.IgnoreCase)
- {
- regex = new Regex(parsedString, RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout);
- }
- else
- {
- regex = new Regex(parsedString, RegexOptions.Compiled, RegexTimeout);
- }
-
- res.Conditions.ConditionList.Add(new Condition { Input = input, Match = new RegexMatch(regex, parsedCondRes.Negate) });
- }
- break;
- case MatchType.IsDirectory:
- {
- res.Conditions.ConditionList.Add(new Condition { Input = input, Match = new IsDirectoryMatch(parsedCondRes.Negate) });
- }
- break;
- case MatchType.IsFile:
- {
- res.Conditions.ConditionList.Add(new Condition { Input = input, Match = new IsFileMatch(parsedCondRes.Negate) });
- }
- break;
- default:
- // TODO don't this this can ever be thrown
- ThrowUrlFormatException(condition, "Unrecognized matchType");
- break;
- }
- }
- break;
- case PatternSyntax.WildCard:
- throw new NotImplementedException("Wildcard syntax is not supported");
- case PatternSyntax.ExactMatch:
- parsedString = condition.Attribute(RewriteTags.Pattern)?.Value;
- if (parsedString == null)
- {
- ThrowUrlFormatException(condition, "Pattern match does not have an associated pattern attribute in condition");
- }
- res.Conditions.ConditionList.Add(new Condition { Input = input, Match = new ExactMatch(parsedCondRes.IgnoreCase, parsedString, parsedCondRes.Negate) });
- break;
- default:
- ThrowUrlFormatException(condition, "Unrecognized pattern syntax");
- break;
- }
}
- private static void CreateUrlAction(XElement urlAction, UrlRewriteRule res, bool globalRule)
+ private static void ParseUrlAction(XElement urlAction, UrlRewriteRuleBuilder builder, bool stopProcessing)
{
-
- var actionRes = new ParsedUrlAction();
-
ActionType actionType;
- if (Enum.TryParse(urlAction.Attribute(RewriteTags.Type)?.Value, out actionType))
+ if (!Enum.TryParse(urlAction.Attribute(RewriteTags.Type)?.Value, out actionType))
{
- actionRes.Type = actionType;
+ actionType = ActionType.None;
}
- bool parseBool;
- if (bool.TryParse(urlAction.Attribute(RewriteTags.AppendQuery)?.Value, out parseBool))
+ bool appendQuery;
+ if (!bool.TryParse(urlAction.Attribute(RewriteTags.AppendQueryString)?.Value, out appendQuery))
{
- actionRes.AppendQueryString = parseBool;
- }
-
- if (bool.TryParse(urlAction.Attribute(RewriteTags.LogRewrittenUrl)?.Value, out parseBool))
- {
- actionRes.LogRewrittenUrl = parseBool;
+ appendQuery = true;
}
RedirectType redirectType;
- if (Enum.TryParse(urlAction.Attribute(RewriteTags.RedirectType)?.Value, out redirectType))
+ if (!Enum.TryParse(urlAction.Attribute(RewriteTags.RedirectType)?.Value, out redirectType))
{
- actionRes.RedirectType = redirectType;
+ redirectType = RedirectType.Permanent;
}
try
{
- actionRes.Url = InputParser.ParseInputString(urlAction.Attribute(RewriteTags.Url)?.Value);
+ var input = InputParser.ParseInputString(urlAction.Attribute(RewriteTags.Url)?.Value);
+ builder.AddUrlAction(input, actionType, appendQuery, stopProcessing, (int)redirectType);
}
catch (FormatException formatException)
{
ThrowUrlFormatException(urlAction, formatException.Message, formatException);
}
-
- CreateUrlActionFromParsedAction(urlAction, actionRes, globalRule, res);
- }
-
- private static void CreateUrlActionFromParsedAction(XElement urlAction, ParsedUrlAction actionRes, bool globalRule, UrlRewriteRule res)
- {
- switch (actionRes.Type)
- {
- case ActionType.None:
- res.Action = new VoidAction();
- break;
- case ActionType.Rewrite:
- if (actionRes.AppendQueryString)
- {
- res.Action = new RewriteAction(res.StopProcessing ? RuleTerminiation.StopRules : RuleTerminiation.Continue, actionRes.Url, clearQuery: false);
- }
- else
- {
- res.Action = new RewriteAction(res.StopProcessing ? RuleTerminiation.StopRules : RuleTerminiation.Continue, actionRes.Url, clearQuery: true);
- }
- break;
- case ActionType.Redirect:
- if (actionRes.AppendQueryString)
- {
- res.Action = new RedirectAction((int)actionRes.RedirectType, actionRes.Url);
- }
- else
- {
- res.Action = new RedirectClearQueryAction((int)actionRes.RedirectType, actionRes.Url);
- }
- break;
- case ActionType.AbortRequest:
- ThrowUrlFormatException(urlAction, "Abort Requests are not supported.");
- break;
- case ActionType.CustomResponse:
- // TODO
- ThrowUrlFormatException(urlAction, "Custom Responses are not supported");
- break;
- }
}
private static void ThrowUrlFormatException(XElement element, string message)
@@ -342,6 +218,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
var col = ((IXmlLineInfo)element).LinePosition;
throw new FormatException(Resources.FormatError_UrlRewriteParseError(message, line, col));
}
+
private static void ThrowUrlFormatException(XElement element, string message, Exception ex)
{
var line = ((IXmlLineInfo)element).LineNumber;
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteRuleBuilder.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteRuleBuilder.cs
new file mode 100644
index 0000000000..ccee529c0a
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteRuleBuilder.cs
@@ -0,0 +1,168 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlActions;
+using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlMatches;
+
+namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
+{
+ public class UrlRewriteRuleBuilder
+ {
+ private readonly TimeSpan RegexTimeout = TimeSpan.FromMilliseconds(1);
+
+ public string Name { get; set; }
+ public bool Enabled { get; set; }
+
+ private UrlMatch _initialMatch;
+ private Conditions _conditions;
+ private UrlAction _action;
+
+ public UrlRewriteRule Build()
+ {
+ // TODO some of these are required fields, throw if null?
+ var rule = new UrlRewriteRule();
+ rule.Action = _action;
+ rule.Conditions = _conditions;
+ rule.InitialMatch = _initialMatch;
+ rule.Name = Name;
+ return rule;
+ }
+
+ public void AddUrlAction(Pattern url, ActionType actionType = ActionType.None, bool appendQueryString = true, bool stopProcessing = false, int statusCode = StatusCodes.Status301MovedPermanently)
+ {
+ switch (actionType)
+ {
+ case ActionType.None:
+ _action = new VoidAction();
+ break;
+ case ActionType.Rewrite:
+ if (appendQueryString)
+ {
+ _action = new RewriteAction(stopProcessing ? RuleTerminiation.StopRules : RuleTerminiation.Continue, url, clearQuery: false);
+ }
+ else
+ {
+ _action = new RewriteAction(stopProcessing ? RuleTerminiation.StopRules : RuleTerminiation.Continue, url, clearQuery: true);
+ }
+ break;
+ case ActionType.Redirect:
+ if (appendQueryString)
+ {
+ _action = new RedirectAction(statusCode, url);
+ }
+ else
+ {
+ _action = new RedirectClearQueryAction(statusCode, url);
+ }
+ break;
+ case ActionType.AbortRequest:
+ throw new FormatException("Abort Requests are not supported");
+ case ActionType.CustomResponse:
+ // TODO
+ throw new FormatException("Custom Responses are not supported");
+ }
+ }
+
+ public void AddUrlMatch(string input, bool ignoreCase = true, bool negate = false, PatternSyntax patternSyntax = PatternSyntax.ECMAScript)
+ {
+ switch (patternSyntax)
+ {
+ case PatternSyntax.ECMAScript:
+ {
+ if (ignoreCase)
+ {
+ var regex = new Regex(input, RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout);
+ _initialMatch = new RegexMatch(regex, negate);
+ }
+ else
+ {
+ var regex = new Regex(input, RegexOptions.Compiled, RegexTimeout);
+ _initialMatch = new RegexMatch(regex, negate);
+ }
+ break;
+ }
+ case PatternSyntax.WildCard:
+ throw new NotImplementedException("Wildcard syntax is not supported");
+ case PatternSyntax.ExactMatch:
+ _initialMatch = new ExactMatch(ignoreCase, input, negate);
+ break;
+ }
+ }
+
+ // TODO make this take two overloads and handle regex vs non regex case.
+ public void AddUrlCondition(Pattern input, string pattern, PatternSyntax patternSyntax, MatchType matchType, bool ignoreCase, bool negate)
+ {
+ if (_conditions == null)
+ {
+ AddUrlConditions(LogicalGrouping.MatchAll, trackingAllCaptures: false);
+ }
+ switch (patternSyntax)
+ {
+ case PatternSyntax.ECMAScript:
+ {
+ switch (matchType)
+ {
+ case MatchType.Pattern:
+ {
+ if (pattern == null)
+ {
+ throw new FormatException("Match does not have an associated pattern attribute in condition");
+ }
+
+ Regex regex = null;
+ if (ignoreCase)
+ {
+ regex = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout);
+ }
+ else
+ {
+ regex = new Regex(pattern, RegexOptions.Compiled, RegexTimeout);
+ }
+
+ _conditions.ConditionList.Add(new Condition { Input = input, Match = new RegexMatch(regex, negate) });
+ break;
+ }
+ case MatchType.IsDirectory:
+ {
+ _conditions.ConditionList.Add(new Condition { Input = input, Match = new IsDirectoryMatch(negate) });
+ break;
+ }
+ case MatchType.IsFile:
+ {
+ _conditions.ConditionList.Add(new Condition { Input = input, Match = new IsFileMatch(negate) });
+ break;
+ }
+ default:
+ // TODO new exception handling
+ throw new FormatException("Unrecognized matchType");
+ }
+ break;
+ }
+ case PatternSyntax.WildCard:
+ throw new NotImplementedException("Wildcard syntax is not supported");
+ case PatternSyntax.ExactMatch:
+ if (pattern == null)
+ {
+ throw new FormatException("Match does not have an associated pattern attribute in condition");
+ }
+ _conditions.ConditionList.Add(new Condition { Input = input, Match = new ExactMatch(ignoreCase, pattern, negate) });
+ break;
+ default:
+ throw new FormatException("Unrecognized pattern syntax");
+ }
+ }
+
+ public void AddUrlConditions(LogicalGrouping logicalGrouping, bool trackingAllCaptures)
+ {
+ var conditions = new Conditions();
+ conditions.ConditionList = new List();
+ conditions.MatchType = logicalGrouping;
+ conditions.TrackingAllCaptures = trackingAllCaptures;
+ _conditions = conditions;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewriteRule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewriteRule.cs
index 9bd9c7e155..4295548204 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewriteRule.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewriteRule.cs
@@ -7,8 +7,6 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
{
public string Name { get; set; }
public bool Enabled { get; set; } = true;
- public PatternSyntax PatternSyntax { get; set; }
- public bool StopProcessing { get; set; }
public UrlMatch InitialMatch { get; set; }
public Conditions Conditions { get; set; }
public UrlAction Action { get; set; }
@@ -19,8 +17,10 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
{
return RuleResult.Continue;
}
+
// Due to the path string always having a leading slash,
// remove it from the path before regex comparison
+ // TODO may need to check if there is a leading slash and remove conditionally
var initMatchRes = InitialMatch.Evaluate(context.HttpContext.Request.Path.ToString().Substring(1), context);
if (!initMatchRes.Success)
@@ -28,10 +28,14 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
return RuleResult.Continue;
}
- var condMatchRes = Conditions.Evaluate(context, initMatchRes);
- if (!condMatchRes.Success)
+ MatchResults condMatchRes = null;
+ if (Conditions != null)
{
- return RuleResult.Continue;
+ condMatchRes = Conditions.Evaluate(context, initMatchRes);
+ if (!condMatchRes.Success)
+ {
+ return RuleResult.Continue;
+ }
}
// at this point we know the rule passed, evaluate the replacement.
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/CodeRules/MiddlewareTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/CodeRules/MiddlewareTests.cs
new file mode 100644
index 0000000000..1f08becb6c
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/CodeRules/MiddlewareTests.cs
@@ -0,0 +1,90 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.TestHost;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.CodeRules
+{
+ public class MiddlewareTests
+ {
+ [Fact]
+ public async Task CheckRewritePath()
+ {
+ var options = new RewriteOptions().RewriteRule("(.*)", "http://example.com/{R:1}");
+ var builder = new WebHostBuilder()
+ .Configure(app =>
+ {
+ app.UseRewriter(options);
+ app.UseRewriter(options);
+ app.Run(context => context.Response.WriteAsync(
+ context.Request.Scheme +
+ "://" +
+ context.Request.Host +
+ context.Request.Path +
+ context.Request.QueryString));
+ });
+ var server = new TestServer(builder);
+
+ var response = await server.CreateClient().GetStringAsync("foo");
+
+ Assert.Equal(response, "http://example.com/foo");
+ }
+
+ [Fact]
+ public async Task CheckRedirectPath()
+ {
+ var options = new RewriteOptions().RedirectRule("(.*)","http://example.com/{R:1}", statusCode: 301);
+ var builder = new WebHostBuilder()
+ .Configure(app =>
+ {
+ app.UseRewriter(options);
+ });
+ var server = new TestServer(builder);
+
+ var response = await server.CreateClient().GetAsync("foo");
+
+ Assert.Equal(response.Headers.Location.OriginalString, "http://example.com/foo");
+ }
+
+ [Fact]
+ public async Task CheckRewriteToHttps()
+ {
+ var options = new RewriteOptions().RewriteToHttps();
+ var builder = new WebHostBuilder()
+ .Configure(app =>
+ {
+ app.UseRewriter(options);
+ app.UseRewriter(options);
+ app.Run(context => context.Response.WriteAsync(
+ context.Request.Scheme));
+ });
+ var server = new TestServer(builder);
+
+ var response = await server.CreateClient().GetStringAsync(new Uri("http://example.com"));
+
+ Assert.Equal(response, "https");
+ }
+
+ [Fact]
+ public async Task CheckRedirectToHttps()
+ {
+ var options = new RewriteOptions().RedirectToHttps(statusCode: 301);
+ var builder = new WebHostBuilder()
+ .Configure(app =>
+ {
+ app.UseRewriter(options);
+ });
+ var server = new TestServer(builder);
+
+ var response = await server.CreateClient().GetAsync(new Uri("http://example.com"));
+
+ Assert.Equal(response.Headers.Location.OriginalString, "https://example.com/");
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FileParserTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FileParserTests.cs
index 4cdfe347aa..214bc87991 100644
--- a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FileParserTests.cs
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FileParserTests.cs
@@ -150,8 +150,6 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
Action = new RewriteAction(RuleTerminiation.Continue, InputParser.ParseInputString(Url), clearQuery: false),
Name = name,
Enabled = enabled,
- StopProcessing = stopProcessing,
- PatternSyntax = patternSyntax,
InitialMatch = new RegexMatch(new Regex("^OFF$"), false)
{
},
@@ -164,29 +162,37 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
};
}
- private void AssertUrlRewriteRuleEquality(List expected, List actual)
+ private void AssertUrlRewriteRuleEquality(List actual, List expected)
{
- Assert.Equal(expected.Count, actual.Count);
- for (var i = 0; i < expected.Count; i++)
+ Assert.Equal(actual.Count, expected.Count);
+ for (var i = 0; i < actual.Count; i++)
{
- var r1 = expected[i];
- var r2 = actual[i];
+ var r1 = actual[i];
+ var r2 = expected[i];
Assert.Equal(r1.Name, r2.Name);
Assert.Equal(r1.Enabled, r2.Enabled);
- Assert.Equal(r1.StopProcessing, r2.StopProcessing);
- Assert.Equal(r1.PatternSyntax, r2.PatternSyntax);
// TODO conditions, url pattern, initial match regex
- Assert.Equal(r1.Conditions.MatchType, r2.Conditions.MatchType);
- Assert.Equal(r1.Conditions.TrackingAllCaptures, r2.Conditions.TrackingAllCaptures);
- Assert.Equal(r1.Conditions.ConditionList.Count, r2.Conditions.ConditionList.Count);
-
- for (var j = 0; j < r1.Conditions.ConditionList.Count; j++)
+ if (r1.Conditions == null)
{
- var c1 = r1.Conditions.ConditionList[j];
- var c2 = r2.Conditions.ConditionList[j];
- Assert.Equal(c1.Input.PatternSegments.Count, c2.Input.PatternSegments.Count);
+ Assert.Equal(r2.Conditions.ConditionList.Count, 0);
+ }
+ else if (r2.Conditions == null)
+ {
+ Assert.Equal(r1.Conditions.ConditionList.Count, 0);
+ }
+ else
+ {
+ Assert.Equal(r1.Conditions.MatchType, r2.Conditions.MatchType);
+ Assert.Equal(r1.Conditions.TrackingAllCaptures, r2.Conditions.TrackingAllCaptures);
+ Assert.Equal(r1.Conditions.ConditionList.Count, r2.Conditions.ConditionList.Count);
+ for (var j = 0; j < r1.Conditions.ConditionList.Count; j++)
+ {
+ var c1 = r1.Conditions.ConditionList[j];
+ var c2 = r2.Conditions.ConditionList[j];
+ Assert.Equal(c1.Input.PatternSegments.Count, c2.Input.PatternSegments.Count);
+ }
}
}
}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FormatExceptionHandlingTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FormatExceptionHandlingTests.cs
index 6a4f5f47e0..7ba0bc07a0 100644
--- a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FormatExceptionHandlingTests.cs
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FormatExceptionHandlingTests.cs
@@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
",
- "Could not parse the UrlRewrite file. Message: 'Abort Requests are not supported.'. Line number '5': '14'.")]
+ "Could not parse the UrlRewrite file. Message: 'Abort Requests are not supported'. Line number '5': '14'.")]
[InlineData(
@"
@@ -54,6 +54,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
+
",
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/MiddleWareTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/MiddleWareTests.cs
index a34101b375..f2018d20b9 100644
--- a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/MiddleWareTests.cs
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/MiddleWareTests.cs
@@ -19,13 +19,13 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
public async Task Invoke_RedirectPathToPathAndQuery()
{
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"
-
-
-
-
-
-
- "));
+
+
+
+
+
+
+ "));
var builder = new WebHostBuilder()
.Configure(app =>
{
@@ -43,13 +43,13 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
public async Task Invoke_RewritePathToPathAndQuery()
{
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"
-
-
-
-
-
-
- "));
+
+
+
+
+
+
+ "));
var builder = new WebHostBuilder()
.Configure(app =>
{
@@ -121,13 +121,13 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"
-
-
-
-
-
-
-
+
+
+
+
+
+
+
"));
var builder = new WebHostBuilder()
@@ -148,13 +148,13 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"
-
-
-
-
-
-
-
+
+
+
+
+
+
+
"));
var builder = new WebHostBuilder()
@@ -174,13 +174,13 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
{
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"
-
-
-
-
-
-
-
+
+
+
+
+
+
+
"));
var builder = new WebHostBuilder()
@@ -200,13 +200,13 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
{
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"
-
-
-
-
-
-
-
+
+
+
+
+
+
+
"));
var builder = new WebHostBuilder()
@@ -214,10 +214,10 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
{
app.UseRewriter(options);
app.Run(context => context.Response.WriteAsync(
- context.Request.Scheme +
+ context.Request.Scheme +
"://" +
context.Request.Host +
- context.Request.Path +
+ context.Request.Path +
context.Request.QueryString));
});
var server = new TestServer(builder);
@@ -232,10 +232,10 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
{
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"
-
-
-
-
+
+
+
+
"));
var builder = new WebHostBuilder()