diff --git a/samples/RewriteSample/Rewrite.txt b/samples/RewriteSample/Rewrite.txt
index 574f251600..23d4948c18 100644
--- a/samples/RewriteSample/Rewrite.txt
+++ b/samples/RewriteSample/Rewrite.txt
@@ -1,10 +1,3 @@
-# Ensure Https
-RewriteCond %{HTTPS} off
-RewriteRule ^(.*)$ https://www.example.com$1 [L]
-
-# Rewrite path with additional sub directory
-RewriteRule ^(.*)$ /foo$1
-
-# Forbid a certain url from being accessed
-RewriteRule /bar - [F]
-RewriteRule /bar/ - [F]
+# Rewrite path with additional sub directory
+RewriteCond %{QUERY_STRING} id=20
+RewriteRule ^(.*)$ - [G]
diff --git a/samples/RewriteSample/Startup.cs b/samples/RewriteSample/Startup.cs
index a232a4bf45..ea80638c30 100644
--- a/samples/RewriteSample/Startup.cs
+++ b/samples/RewriteSample/Startup.cs
@@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Rewrite;
-using Microsoft.AspNetCore.Rewrite.Internal;
namespace RewriteSample
{
@@ -26,16 +25,11 @@ namespace RewriteSample
// (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()
+ .Rewrite(@"foo/(\d+)", "foo?id={R:1}")
.ImportFromUrlRewrite(hostingEnv, "UrlRewrite.xml")
- .ImportFromModRewrite(hostingEnv, "Rewrite.txt")
- .RedirectToHttps(StatusCodes.Status307TemporaryRedirect)
- .RewriteRule("/foo/(.*)/bar", "{R:1}/bar")
- .AddRule(ctx =>
- {
- ctx.HttpContext.Request.Path = "/index";
- return RuleResult.Continue;
- }));
+ .ImportFromModRewrite(hostingEnv, "Rewrite.txt"));
app.Run(context => context.Response.WriteAsync($"Rewritten Url: {context.Request.Path + context.Request.QueryString}"));
}
diff --git a/samples/RewriteSample/UrlRewrite.xml b/samples/RewriteSample/UrlRewrite.xml
index 9ef1097666..9d9e089676 100644
--- a/samples/RewriteSample/UrlRewrite.xml
+++ b/samples/RewriteSample/UrlRewrite.xml
@@ -1,8 +1,8 @@
-
-
-
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.Rewrite/CodeRewriteExtensions.cs b/src/Microsoft.AspNetCore.Rewrite/CodeRewriteExtensions.cs
deleted file mode 100644
index 983ae1e36a..0000000000
--- a/src/Microsoft.AspNetCore.Rewrite/CodeRewriteExtensions.cs
+++ /dev/null
@@ -1,104 +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;
-using System.Collections.Generic;
-using Microsoft.AspNetCore.Rewrite.Internal;
-using Microsoft.AspNetCore.Rewrite.Internal.CodeRules;
-using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite;
-
-namespace Microsoft.AspNetCore.Rewrite
-{
- ///
- /// The builder to a list of rules for and
- ///
- public static class CodeRewriteExtensions
- {
- ///
- /// Adds a rule to the current rules.
- ///
- /// The UrlRewrite options.
- /// A rule to be added to the current rules.
- public static RewriteOptions AddRule(this RewriteOptions options, Rule rule)
- {
- options.Rules.Add(rule);
- return options;
- }
-
- ///
- /// Adds a list of rules to the current rules.
- ///
- /// The UrlRewrite options.
- /// A list of rules.
- public static RewriteOptions AddRules(this RewriteOptions options, List rules)
- {
- options.Rules.AddRange(rules);
- return options;
- }
-
- public static RewriteOptions RewriteRule(this RewriteOptions options, string regex, string onMatch)
- {
- 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 = new InputParser().ParseInputString(onMatch);
-
- builder.AddUrlMatch(regex);
- builder.AddUrlAction(pattern, actionType: ActionType.Rewrite, stopProcessing: stopProcessing);
- options.Rules.Add(builder.Build());
- return options;
- }
-
- public static RewriteOptions RedirectRule(this RewriteOptions options, string regex, string onMatch, int statusCode)
- {
- 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 = new InputParser().ParseInputString(onMatch);
-
- builder.AddUrlMatch(regex);
- builder.AddUrlAction(pattern, actionType: ActionType.Redirect, stopProcessing: stopProcessing);
- options.Rules.Add(builder.Build());
- return options;
- }
-
- public static RewriteOptions RedirectToHttps(this RewriteOptions options, int statusCode)
- {
- return RedirectToHttps(options, statusCode, null);
- }
-
- public static RewriteOptions RedirectToHttps(this RewriteOptions options, int statusCode, int? sslPort)
- {
- options.Rules.Add(new RedirectToHttpsRule { StatusCode = statusCode, SSLPort = sslPort });
- return options;
- }
-
- public static RewriteOptions RewriteToHttps(this RewriteOptions options)
- {
- return RewriteToHttps(options, sslPort: null, stopProcessing: false);
- }
-
- public static RewriteOptions RewriteToHttps(this RewriteOptions options, int? sslPort)
- {
- 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;
- }
-
- public static RewriteOptions AddRule(this RewriteOptions options, Func rule)
- {
- options.Rules.Add(new FunctionalRule { OnApplyRule = rule});
- return options;
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/FunctionalRule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/DelegateRule.cs
similarity index 53%
rename from src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/FunctionalRule.cs
rename to src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/DelegateRule.cs
index eccf9e735f..72216f0abc 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/FunctionalRule.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/DelegateRule.cs
@@ -5,9 +5,14 @@ using System;
namespace Microsoft.AspNetCore.Rewrite.Internal.CodeRules
{
- public class FunctionalRule : Rule
+ public class DelegateRule : Rule
{
- public Func OnApplyRule { get; set; }
- public override RuleResult ApplyRule(RewriteContext context) => OnApplyRule(context);
+ private readonly Func _onApplyRule;
+
+ public DelegateRule(Func onApplyRule)
+ {
+ _onApplyRule = onApplyRule;
+ }
+ public override RuleResult ApplyRule(RewriteContext context) => _onApplyRule(context);
}
}
\ 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
deleted file mode 100644
index bcb15fda25..0000000000
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/CodeRules/RewriteToHttpsRule.cs
+++ /dev/null
@@ -1,36 +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 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)
- {
- 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;
- return StopProcessing ? RuleResult.StopRules: RuleResult.Continue;
- }
- return RuleResult.Continue;
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/Conditions.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ConditionEvaluator.cs
similarity index 78%
rename from src/Microsoft.AspNetCore.Rewrite/Internal/Conditions.cs
rename to src/Microsoft.AspNetCore.Rewrite/Internal/ConditionEvaluator.cs
index d8154c6b1d..4407ec3ce8 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/Conditions.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ConditionEvaluator.cs
@@ -5,15 +5,14 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.Rewrite.Internal
{
- public class Conditions
+ public static class ConditionHelper
{
- public List ConditionList { get; set; } = new List();
- public MatchResults Evaluate(RewriteContext context, MatchResults ruleMatch)
+ public static MatchResults Evaluate(IEnumerable conditions, RewriteContext context, MatchResults ruleMatch)
{
MatchResults prevCond = null;
var orSucceeded = false;
- foreach (var condition in ConditionList)
+ foreach (var condition in conditions)
{
if (orSucceeded && condition.OrNext)
{
@@ -30,7 +29,6 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
if (condition.OrNext)
{
orSucceeded = prevCond.Success;
- continue;
}
else if (!prevCond.Success)
{
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionPatternParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionPatternParser.cs
index dc9c8328be..fadd570f97 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionPatternParser.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionPatternParser.cs
@@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
/// A new parsed condition.
public ParsedModRewriteInput ParseActionCondition(string condition)
{
- if (condition == null)
+ if (condition == null)
{
condition = string.Empty;
}
@@ -120,7 +120,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
}
// Capture the rest of the string guarantee validity.
- results.Operand = condition.Substring(context.GetIndex());
+ results.Operand = condition.Substring(context.GetIndex());
if (IsValidActionCondition(results))
{
return results;
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/FileParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/FileParser.cs
index 2f16c8af08..baec9e2c4f 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/FileParser.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/FileParser.cs
@@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
{
public class FileParser
{
- public List Parse(TextReader input)
+ public IList Parse(TextReader input)
{
string line;
var rules = new List();
@@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
builder.AddAction(pattern, flags);
rules.Add(builder.Build());
builder = new RuleBuilder();
- }
+ }
catch (FormatException formatException)
{
throw new FormatException(Resources.FormatError_ModRewriteGeneralParseError(lineNum), formatException);
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ModRewriteRedirectAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ModRewriteRedirectAction.cs
index 0e47a527ef..75bc8aa0cc 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ModRewriteRedirectAction.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ModRewriteRedirectAction.cs
@@ -15,10 +15,10 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
public bool EscapeBackReferences { get; }
public ModRewriteRedirectAction(
- int statusCode,
- Pattern pattern,
- bool queryStringAppend,
- bool queryStringDelete,
+ int statusCode,
+ Pattern pattern,
+ bool queryStringAppend,
+ bool queryStringDelete,
bool escapeBackReferences)
{
StatusCode = statusCode;
@@ -42,19 +42,11 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
// always add to location header.
// TODO check for false positives
var split = pattern.IndexOf('?');
- if (split >= 0)
+ if (split >= 0 && QueryStringAppend)
{
- QueryString query;
- if (QueryStringAppend)
- {
- query = context.HttpContext.Request.QueryString.Add(
- QueryString.FromUriComponent(
- pattern.Substring(split)));
- }
- else
- {
- query = QueryString.FromUriComponent(pattern.Substring(split));
- }
+ var query = context.HttpContext.Request.QueryString.Add(
+ QueryString.FromUriComponent(
+ pattern.Substring(split)));
// not using the response.redirect here because status codes may be 301, 302, 307, 308
context.HttpContext.Response.Headers[HeaderNames.Location] = pattern.Substring(0, split) + query;
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ModRewriteRewriteAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ModRewriteRewriteAction.cs
index 419bd0f440..01cb99dd24 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ModRewriteRewriteAction.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ModRewriteRewriteAction.cs
@@ -16,8 +16,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
public bool EscapeBackReferences { get; }
public ModRewriteRewriteAction(
- RuleResult result,
- Pattern pattern,
+ RuleResult result,
+ Pattern pattern,
bool queryStringAppend,
bool queryStringDelete,
bool escapeBackReferences)
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleBuilder.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleBuilder.cs
index db0490745c..8190431803 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleBuilder.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleBuilder.cs
@@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
{
public class RuleBuilder
{
- private Conditions _conditions;
+ private IList _conditions;
private UrlAction _action;
private UrlMatch _match;
private List _preActions;
@@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
{
if (_conditions == null)
{
- _conditions = new Conditions();
+ _conditions = new List();
}
var condition = new Condition();
@@ -147,7 +147,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
}
break;
}
- _conditions.ConditionList.Add(condition);
+ _conditions.Add(condition);
}
public void AddMatch(
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleRegexParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleRegexParser.cs
index 67368cc6df..bdc6273d02 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleRegexParser.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleRegexParser.cs
@@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
}
else
{
- return new ParsedModRewriteInput { Invert = false, Operand = regex};
+ return new ParsedModRewriteInput { Invert = false, Operand = regex };
}
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ServerVariables.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ServerVariables.cs
index 863fd44bba..ebddffba19 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ServerVariables.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ServerVariables.cs
@@ -106,7 +106,6 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
case "HTTP2":
throw new NotImplementedException("Http2 server variable is not supported");
case "IS_SUBREQ":
- // TODO maybe can do this? context.Request.HttpContext ?
throw new NotImplementedException("Is-Subrequest server variable is not supported");
case "REQUEST_FILENAME":
return new RequestFileNameSegment();
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/TestStringParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/TestStringParser.cs
index 002c69fa40..a87d9b1ed6 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/TestStringParser.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/TestStringParser.cs
@@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
var ruleVariable = context.Capture();
context.Back();
var parsedIndex = int.Parse(ruleVariable);
-
+
results.Add(new RuleMatchSegment(parsedIndex));
}
else
@@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
/// The ParserContext
/// The List of results which the new condition parameter will be added.
/// true
- private static void ParseConditionParameter(ParserContext context, List results)
+ private static void ParseConditionParameter(ParserContext context, IList results)
{
// Parse { }
if (context.Current == OpenBrace)
@@ -146,7 +146,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
///
///
///
- private static void ParseLiteral(ParserContext context, List results)
+ private static void ParseLiteral(ParserContext context, IList results)
{
context.Mark();
string literal;
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Tokenizer.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Tokenizer.cs
index 6b51553dbb..1ecabd093d 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Tokenizer.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Tokenizer.cs
@@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
///
/// The rule to tokenize.
/// A list of tokens.
- public List Tokenize(string rule)
+ public IList Tokenize(string rule)
{
// TODO make list of strings a reference to the original rule? (run into problems with escaped spaces).
// TODO handle "s and probably replace \ character with no slash.
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewriteRule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewriteRule.cs
index 6d7e090b9a..eb54eed72a 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewriteRule.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewriteRule.cs
@@ -2,18 +2,18 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
-using Microsoft.AspNetCore.Rewrite.Internal;
+using Microsoft.AspNetCore.Rewrite.Logging;
namespace Microsoft.AspNetCore.Rewrite.Internal
{
public class ModRewriteRule : Rule
{
- public UrlMatch InitialMatch { get; set; }
- public Conditions Conditions { get; set; }
- public UrlAction Action { get; set; }
- public List PreActions { get; set; }
+ public UrlMatch InitialMatch { get; }
+ public IList Conditions { get; }
+ public UrlAction Action { get; }
+ public IList PreActions { get; }
- public ModRewriteRule(UrlMatch initialMatch, Conditions conditions, UrlAction urlAction, List preActions)
+ public ModRewriteRule(UrlMatch initialMatch, IList conditions, UrlAction urlAction, IList preActions)
{
Conditions = conditions;
InitialMatch = initialMatch;
@@ -28,21 +28,24 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
if (!initMatchRes.Success)
{
+ context.Logger?.ModRewriteDidNotMatchRule();
return RuleResult.Continue;
}
MatchResults condMatchRes = null;
if (Conditions != null)
{
- condMatchRes = Conditions.Evaluate(context, initMatchRes);
+ condMatchRes = ConditionHelper.Evaluate(Conditions, context, initMatchRes);
if (!condMatchRes.Success)
{
+ context.Logger?.ModRewriteDidNotMatchRule();
return RuleResult.Continue;
}
}
// At this point, we know our rule passed, first apply pre conditions,
// which can modify things like the cookie or env, and then apply the action
+ context.Logger?.ModRewriteMatchedRule();
foreach (var preAction in PreActions)
{
preAction.ApplyAction(context.HttpContext, initMatchRes, condMatchRes);
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegment.cs
index 6ea96b915f..0cc7b7ddce 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegment.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegment.cs
@@ -1,14 +1,10 @@
// 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 Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite;
-
namespace Microsoft.AspNetCore.Rewrite.Internal
{
public abstract class PatternSegment
{
- // Match from prevRule, Match from prevCond
public abstract string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch);
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/DateTimeSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/DateTimeSegment.cs
index 4238ebb0fb..2d5202eeb8 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/DateTimeSegment.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/DateTimeSegment.cs
@@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
public DateTimeSegment(string segment)
{
- switch(segment)
+ switch (segment)
{
case "TIME_YEAR":
_portion = DateTimePortion.Year;
@@ -24,28 +24,29 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
_portion = DateTimePortion.Day;
break;
case "TIME_HOUR":
- _portion = DateTimePortion.Day;
+ _portion = DateTimePortion.Hour;
break;
case "TIME_MIN":
- _portion = DateTimePortion.Day;
+ _portion = DateTimePortion.Minute;
break;
case "TIME_SEC":
- _portion = DateTimePortion.Day;
+ _portion = DateTimePortion.Second;
break;
case "TIME_WDAY":
- _portion = DateTimePortion.Day;
+ _portion = DateTimePortion.DayOfWeek;
break;
case "TIME":
- _portion = DateTimePortion.Day;
+ _portion = DateTimePortion.Time;
break;
default:
- throw new FormatException("Unsupported segment: " + segment);
+ throw new FormatException($"Unsupported segment: '{segment}'");
}
}
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
{
- switch (_portion) {
+ switch (_portion)
+ {
case DateTimePortion.Year:
return DateTimeOffset.UtcNow.Year.ToString(CultureInfo.InvariantCulture);
case DateTimePortion.Month:
@@ -67,7 +68,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
}
}
- private enum DateTimePortion {
+ private enum DateTimePortion
+ {
Year,
Month,
Day,
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/HeaderSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/HeaderSegment.cs
index cd506c75d2..5327c969fb 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/HeaderSegment.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/HeaderSegment.cs
@@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
public class HeaderSegment : PatternSegment
{
private readonly string _header;
-
+
public HeaderSegment(string header)
{
_header = header;
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/UrlEncodeSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/UrlEncodeSegment.cs
index 5bca22d5ff..e5ad2aac30 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/UrlEncodeSegment.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/UrlEncodeSegment.cs
@@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
public class UrlEncodeSegment : PatternSegment
{
private readonly Pattern _pattern;
-
+
public UrlEncodeSegment(Pattern pattern)
{
_pattern = pattern;
@@ -17,10 +17,14 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
{
- var tempBuilder = context.Builder;
+ var oldBuilder = context.Builder;
+ // PERF
+ // Because we need to be able to evaluate multiple nested patterns,
+ // we provided a new string builder and evaluate the new pattern,
+ // and restore it after evaluation.
context.Builder = new StringBuilder(64);
var pattern = _pattern.Evaluate(context, ruleMatch, condMatch);
- context.Builder = tempBuilder;
+ context.Builder = oldBuilder;
return UrlEncoder.Default.Encode(pattern);
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/PreActions/ChangeCookiePreAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/PreActions/ChangeCookiePreAction.cs
index 13d2dd3ba9..a08506158f 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/PreActions/ChangeCookiePreAction.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/PreActions/ChangeCookiePreAction.cs
@@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PreActions
public override void ApplyAction(HttpContext context, MatchResults ruleMatch, MatchResults condMatch)
{
// modify the cookies
-
+
}
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlAction.cs
index 8f2a8496c8..326d22b377 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlAction.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlAction.cs
@@ -5,7 +5,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
{
public abstract class UrlAction
{
- public Pattern Url { get; set; }
+ protected Pattern Url { get; set; }
public abstract RuleResult ApplyAction(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch);
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/RedirectAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/RedirectAction.cs
index 98df716b27..f0cac6afb7 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/RedirectAction.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/RedirectAction.cs
@@ -1,6 +1,7 @@
// 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 Microsoft.AspNetCore.Http;
using Microsoft.Net.Http.Headers;
@@ -9,25 +10,33 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
public class RedirectAction : UrlAction
{
public int StatusCode { get; }
- public RedirectAction(int statusCode, Pattern pattern)
+ public bool AppendQueryString { get; }
+
+ public RedirectAction(int statusCode, Pattern pattern, bool appendQueryString)
{
StatusCode = statusCode;
Url = pattern;
+ AppendQueryString = appendQueryString;
}
public override RuleResult ApplyAction(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
{
-
var pattern = Url.Evaluate(context, ruleMatch, condMatch);
context.HttpContext.Response.StatusCode = StatusCode;
+ // TODO IIS guarantees that there will be a leading slash
+ if (pattern.IndexOf("://", StringComparison.Ordinal) == -1 && !pattern.StartsWith("/"))
+ {
+ pattern = '/' + pattern;
+ }
+
// url can either contain the full url or the path and query
// always add to location header.
// TODO check for false positives
var split = pattern.IndexOf('?');
- if (split >= 0)
+ if (split >= 0 && AppendQueryString)
{
- var query = context.HttpContext.Request.QueryString.Add(
+ var query = context.HttpContext.Request.QueryString.Add(
QueryString.FromUriComponent(
pattern.Substring(split)));
// not using the HttpContext.Response.redirect here because status codes may be 301, 302, 307, 308
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/RedirectClearQueryAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/RedirectClearQueryAction.cs
deleted file mode 100644
index ec51cf748c..0000000000
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/RedirectClearQueryAction.cs
+++ /dev/null
@@ -1,27 +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 Microsoft.Net.Http.Headers;
-
-namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
-{
- public class RedirectClearQueryAction : UrlAction
- {
- public int StatusCode { get; }
- public RedirectClearQueryAction(int statusCode, Pattern pattern)
- {
- StatusCode = statusCode;
- Url = pattern;
- }
-
- public override RuleResult ApplyAction(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
- {
- var pattern = Url.Evaluate(context, ruleMatch, condMatch);
- context.HttpContext.Response.StatusCode = StatusCode;
-
- // we are clearing the query, so just put the pattern in the location header
- context.HttpContext.Response.Headers[HeaderNames.Location] = pattern;
- return RuleResult.ResponseComplete;
- }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/RewriteAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/RewriteAction.cs
index eb8d59dda2..7c9cd06103 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/RewriteAction.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/RewriteAction.cs
@@ -10,10 +10,10 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
public class RewriteAction : UrlAction
{
private readonly string ForwardSlash = "/";
- public RuleTerminiation Result { get; }
+ public RuleTermination Result { get; }
public bool ClearQuery { get; }
- public RewriteAction(RuleTerminiation result, Pattern pattern, bool clearQuery)
+ public RewriteAction(RuleTermination result, Pattern pattern, bool clearQuery)
{
Result = result;
Url = pattern;
@@ -28,8 +28,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
{
context.HttpContext.Request.QueryString = QueryString.Empty;
}
- // TODO PERF, substrings, object creation, etc.
- if (pattern.IndexOf("://") >= 0)
+
+ if (pattern.IndexOf("://", StringComparison.Ordinal) >= 0)
{
string scheme;
HostString host;
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/FileSizeMatch.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/FileSizeMatch.cs
index d2d6397408..e798b0191c 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/FileSizeMatch.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/FileSizeMatch.cs
@@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
public override MatchResults Evaluate(string input, RewriteContext context)
{
- var fileInfo = context.FileProvider.GetFileInfo(input);
+ var fileInfo = context.StaticFileProvider.GetFileInfo(input);
return fileInfo.Exists && fileInfo.Length > 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IsDirectoryMatch.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IsDirectoryMatch.cs
index 113ff88e2e..b4361c5d31 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IsDirectoryMatch.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IsDirectoryMatch.cs
@@ -6,13 +6,13 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
public class IsDirectoryMatch : UrlMatch
{
public IsDirectoryMatch(bool negate)
- {
+ {
Negate = negate;
}
public override MatchResults Evaluate(string pattern, RewriteContext context)
{
- var res = context.FileProvider.GetFileInfo(pattern).IsDirectory;
+ var res = context.StaticFileProvider.GetFileInfo(pattern).IsDirectory;
return new MatchResults { Success = (res != Negate) };
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IsFileMatch.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IsFileMatch.cs
index 6dc8d9ea0b..e4d4816133 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IsFileMatch.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IsFileMatch.cs
@@ -4,7 +4,7 @@
namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
{
public class IsFileMatch : UrlMatch
- {
+ {
public IsFileMatch(bool negate)
{
Negate = negate;
@@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
public override MatchResults Evaluate(string pattern, RewriteContext context)
{
- var res = context.FileProvider.GetFileInfo(pattern).Exists;
+ var res = context.StaticFileProvider.GetFileInfo(pattern).Exists;
return new MatchResults { Success = (res != Negate) };
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/RegexMatch.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/RegexMatch.cs
index b869285b20..eb880c18ec 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/RegexMatch.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/RegexMatch.cs
@@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
public override MatchResults Evaluate(string pattern, RewriteContext context)
{
var res = _match.Match(pattern);
- return new MatchResults { BackReference = res.Groups, Success = (res.Success != Negate)};
+ return new MatchResults { BackReference = res.Groups, Success = (res.Success != Negate) };
}
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/InputParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/InputParser.cs
index 5fe5038eef..ada89f938d 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/InputParser.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/InputParser.cs
@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
-using Microsoft.AspNetCore.Rewrite.Internal;
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
@@ -60,7 +59,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
return new Pattern(results);
}
- private static void ParseParameter(ParserContext context, List results)
+ private static void ParseParameter(ParserContext context, IList results)
{
context.Mark();
// Four main cases:
@@ -82,7 +81,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
else if (context.Current == Colon)
{
parameter = context.Capture();
-
+
// Only 5 strings to expect here. Case sensitive.
switch (parameter)
{
@@ -165,7 +164,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
return index;
}
- private static void ParseLiteral(ParserContext context, List results)
+ private static void ParseLiteral(ParserContext context, IList results)
{
context.Mark();
string literal;
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ServerVariables.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ServerVariables.cs
index aa5845a872..8a0fad4150 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ServerVariables.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ServerVariables.cs
@@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
-using Microsoft.AspNetCore.Rewrite.Internal;
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
using Microsoft.Net.Http.Headers;
@@ -12,7 +11,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
{
public static PatternSegment FindServerVariable(string serverVariable)
{
- switch(serverVariable)
+ switch (serverVariable)
{
// TODO Add all server variables here.
case "ALL_RAW":
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/FileParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteFileParser.cs
similarity index 97%
rename from src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/FileParser.cs
rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteFileParser.cs
index 6e6cd6419d..9dcd7f4a4a 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/FileParser.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteFileParser.cs
@@ -10,11 +10,11 @@ using System.Xml.Linq;
namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
{
- public class FileParser
+ public class UrlRewriteFileParser
{
private readonly InputParser _inputParser = new InputParser();
- public List Parse(TextReader reader)
+ public IList Parse(TextReader reader)
{
var xmlDoc = XDocument.Load(reader, LoadOptions.SetLineInfo);
var xmlRoot = xmlDoc.Descendants(RewriteTags.Rewrite).FirstOrDefault();
@@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
return null;
}
- private void ParseRules(XElement rules, List result)
+ private void ParseRules(XElement rules, IList result)
{
if (rules == null)
{
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteRuleBuilder.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteRuleBuilder.cs
index 2dad4efcd0..90da1e57d9 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteRuleBuilder.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteRuleBuilder.cs
@@ -13,12 +13,12 @@ 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 IList _conditions;
private UrlAction _action;
private bool _matchAny;
@@ -28,40 +28,28 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
{
throw new InvalidOperationException("Cannot create UrlRewriteRule without action and match");
}
- var rule = new UrlRewriteRule();
- rule.Action = _action;
- rule.Conditions = _conditions;
- rule.InitialMatch = _initialMatch;
- rule.Name = Name;
- return rule;
+
+ return new UrlRewriteRule(Name, _initialMatch, _conditions, _action);
}
-
- public void AddUrlAction(Pattern url, ActionType actionType = ActionType.None, bool appendQueryString = true, bool stopProcessing = false, int statusCode = StatusCodes.Status301MovedPermanently)
+
+ 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(stopProcessing ? RuleResult.StopRules : RuleResult.Continue);
+ _action = new VoidAction(stopProcessing ? RuleResult.StopRules : RuleResult.Continue);
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);
- }
+ _action = new RewriteAction(stopProcessing ? RuleTermination.StopRules : RuleTermination.Continue,
+ url, clearQuery: !appendQueryString);
break;
case ActionType.Redirect:
- if (appendQueryString)
- {
- _action = new RedirectAction(statusCode, url);
- }
- else
- {
- _action = new RedirectClearQueryAction(statusCode, url);
- }
+ _action = new RedirectAction(statusCode, url, appendQueryString);
break;
case ActionType.AbortRequest:
throw new NotImplementedException("Abort Requests are not supported");
@@ -85,14 +73,14 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
else
{
var regex = new Regex(input, RegexOptions.CultureInvariant | RegexOptions.Compiled, RegexTimeout);
- _initialMatch = new RegexMatch(regex, negate);
+ _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);
+ _initialMatch = new ExactMatch(ignoreCase, input, negate);
break;
}
}
@@ -118,27 +106,23 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
throw new FormatException("Match does not have an associated pattern attribute in condition");
}
- Regex regex = null;
- if (ignoreCase)
- {
- regex = new Regex(pattern, RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout);
- }
- else
- {
- regex = new Regex(pattern, RegexOptions.CultureInvariant | RegexOptions.Compiled, RegexTimeout);
- }
-
- _conditions.ConditionList.Add(new Condition { Input = input, Match = new RegexMatch(regex, negate), OrNext = _matchAny});
+ var regex = new Regex(
+ pattern,
+ ignoreCase ? RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase :
+ RegexOptions.CultureInvariant | RegexOptions.Compiled,
+ RegexTimeout);
+
+ _conditions.Add(new Condition { Input = input, Match = new RegexMatch(regex, negate), OrNext = _matchAny });
break;
}
case MatchType.IsDirectory:
{
- _conditions.ConditionList.Add(new Condition { Input = input, Match = new IsDirectoryMatch(negate), OrNext = _matchAny });
+ _conditions.Add(new Condition { Input = input, Match = new IsDirectoryMatch(negate), OrNext = _matchAny });
break;
}
case MatchType.IsFile:
{
- _conditions.ConditionList.Add(new Condition { Input = input, Match = new IsFileMatch(negate), OrNext = _matchAny });
+ _conditions.Add(new Condition { Input = input, Match = new IsFileMatch(negate), OrNext = _matchAny });
break;
}
default:
@@ -153,7 +137,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
{
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), OrNext = _matchAny });
+ _conditions.Add(new Condition { Input = input, Match = new ExactMatch(ignoreCase, pattern, negate), OrNext = _matchAny });
break;
default:
throw new FormatException("Unrecognized pattern syntax");
@@ -162,10 +146,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
public void AddUrlConditions(LogicalGrouping logicalGrouping, bool trackingAllCaptures)
{
- var conditions = new Conditions();
- conditions.ConditionList = new List();
+ _conditions = new List();
_matchAny = logicalGrouping == LogicalGrouping.MatchAny;
- _conditions = conditions;
}
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewriteRule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewriteRule.cs
index 736290b4fa..94a88763ff 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewriteRule.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewriteRule.cs
@@ -1,28 +1,34 @@
// 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.Collections.Generic;
using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Logging;
namespace Microsoft.AspNetCore.Rewrite.Internal
{
public class UrlRewriteRule : Rule
{
- public string Name { get; set; }
- public bool Enabled { get; set; } = true;
- public UrlMatch InitialMatch { get; set; }
- public Conditions Conditions { get; set; }
- public UrlAction Action { get; set; }
+ public string Name { get; }
+ public UrlMatch InitialMatch { get; }
+ public IList Conditions { get; }
+ public UrlAction Action { get; }
+
+ public UrlRewriteRule(string name,
+ UrlMatch initialMatch,
+ IList conditions,
+ UrlAction action)
+ {
+ Name = name;
+ InitialMatch = initialMatch;
+ Conditions = conditions;
+ Action = action;
+ }
public override RuleResult ApplyRule(RewriteContext context)
{
- if (!Enabled)
- {
- 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 path = context.HttpContext.Request.Path;
MatchResults initMatchResults;
if (path == PathString.Empty)
@@ -36,19 +42,22 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
if (!initMatchResults.Success)
{
+ context.Logger?.UrlRewriteDidNotMatchRule(Name);
return RuleResult.Continue;
}
MatchResults condMatchRes = null;
if (Conditions != null)
{
- condMatchRes = Conditions.Evaluate(context, initMatchResults);
+ condMatchRes = ConditionHelper.Evaluate(Conditions, context, initMatchResults);
if (!condMatchRes.Success)
{
+ context.Logger?.UrlRewriteDidNotMatchRule(Name);
return RuleResult.Continue;
}
}
+ context.Logger?.UrlRewriteMatchedRule(Name);
// at this point we know the rule passed, evaluate the replacement.
return Action.ApplyAction(context, initMatchResults, condMatchRes);
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Logging/RewriteMiddlewareLoggingExtensions.cs b/src/Microsoft.AspNetCore.Rewrite/Logging/RewriteMiddlewareLoggingExtensions.cs
new file mode 100644
index 0000000000..0d32fe6cfa
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Rewrite/Logging/RewriteMiddlewareLoggingExtensions.cs
@@ -0,0 +1,88 @@
+// 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 Microsoft.Extensions.Logging;
+
+namespace Microsoft.AspNetCore.Rewrite.Logging
+{
+ internal static class RewriteMiddlewareLoggingExtensions
+ {
+ private static readonly Action _requestContinueResults;
+ private static readonly Action _requestResponseComplete;
+ private static readonly Action _requestStopRules;
+ private static readonly Action _urlRewriteDidNotMatchRule;
+ private static readonly Action _urlRewriteMatchedRule;
+ private static readonly Action _modRewriteDidNotMatchRule;
+ private static readonly Action _modRewriteMatchedRule;
+
+ static RewriteMiddlewareLoggingExtensions()
+ {
+ _requestContinueResults = LoggerMessage.Define(
+ LogLevel.Debug,
+ 1,
+ "Request is continuing in applying rules.");
+ _requestResponseComplete = LoggerMessage.Define(
+ LogLevel.Debug,
+ 2,
+ "Request is done processing, Location header '{Location}' with status code '{StatusCode}'.");
+ _requestStopRules = LoggerMessage.Define(
+ LogLevel.Debug,
+ 3,
+ "Request is done applying rules.");
+ _urlRewriteDidNotMatchRule = LoggerMessage.Define(
+ LogLevel.Debug,
+ 4,
+ "Request did not match current rule '{Name}'.");
+
+ _urlRewriteMatchedRule = LoggerMessage.Define(
+ LogLevel.Debug,
+ 5,
+ "Request matched current UrlRewriteRule '{Name}'.");
+
+ _modRewriteDidNotMatchRule = LoggerMessage.Define(
+ LogLevel.Debug,
+ 6,
+ "Request matched current ModRewriteRule.");
+
+ _modRewriteMatchedRule = LoggerMessage.Define(
+ LogLevel.Debug,
+ 7,
+ "Request matched current ModRewriteRule.");
+ }
+
+ public static void RewriteMiddlewareRequestContinueResults(this ILogger logger)
+ {
+ _requestContinueResults(logger, null);
+ }
+
+ public static void RewriteMiddlewareRequestResponseComplete(this ILogger logger, string location, int statusCode)
+ {
+ _requestResponseComplete(logger, location, statusCode, null);
+ }
+
+ public static void RewriteMiddlewareRequestStopRules(this ILogger logger)
+ {
+ _requestStopRules(logger, null);
+ }
+
+ public static void UrlRewriteDidNotMatchRule(this ILogger logger, string name)
+ {
+ _urlRewriteDidNotMatchRule(logger, name, null);
+ }
+
+ public static void UrlRewriteMatchedRule(this ILogger logger, string name)
+ {
+ _urlRewriteMatchedRule(logger, name, null);
+ }
+
+ public static void ModRewriteDidNotMatchRule(this ILogger logger)
+ {
+ _modRewriteDidNotMatchRule(logger, null);
+ }
+ public static void ModRewriteMatchedRule(this ILogger logger)
+ {
+ _modRewriteMatchedRule(logger, null);
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewriteExtensions.cs b/src/Microsoft.AspNetCore.Rewrite/ModRewriteOptionsExtensions.cs
similarity index 55%
rename from src/Microsoft.AspNetCore.Rewrite/ModRewriteExtensions.cs
rename to src/Microsoft.AspNetCore.Rewrite/ModRewriteOptionsExtensions.cs
index 77dc019956..1ad897b90e 100644
--- a/src/Microsoft.AspNetCore.Rewrite/ModRewriteExtensions.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/ModRewriteOptionsExtensions.cs
@@ -8,24 +8,24 @@ using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite;
namespace Microsoft.AspNetCore.Rewrite
{
- public static class ModRewriteExtensions
+ public static class ModRewriteOptionsExtensions
{
///
/// Imports rules from a mod_rewrite file and adds the rules to current rules.
///
- /// The UrlRewrite options.
- ///
+ /// The Rewrite options.
+ /// The Hosting Environment
/// The path to the file containing mod_rewrite rules.
- public static RewriteOptions ImportFromModRewrite(this RewriteOptions options, IHostingEnvironment hostingEnv, string filePath)
+ public static RewriteOptions ImportFromModRewrite(this RewriteOptions options, IHostingEnvironment hostingEnvironment, string filePath)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
- if (hostingEnv == null)
+ if (hostingEnvironment == null)
{
- throw new ArgumentNullException(nameof(hostingEnv));
+ throw new ArgumentNullException(nameof(hostingEnvironment));
}
if (string.IsNullOrEmpty(filePath))
@@ -33,18 +33,17 @@ namespace Microsoft.AspNetCore.Rewrite
throw new ArgumentException(nameof(filePath));
}
- var path = Path.Combine(hostingEnv.ContentRootPath, filePath);
+ var path = Path.Combine(hostingEnvironment.ContentRootPath, filePath);
using (var stream = File.OpenRead(path))
{
- options.Rules.AddRange(new FileParser().Parse(new StreamReader(stream)));
- };
- return options;
+ return options.ImportFromModRewrite(new StreamReader(stream));
+ }
}
///
/// Imports rules from a mod_rewrite file and adds the rules to current rules.
///
- /// The UrlRewrite options.
+ /// The Rewrite options.
/// Text reader containing a stream of mod_rewrite rules.
public static RewriteOptions ImportFromModRewrite(this RewriteOptions options, TextReader reader)
{
@@ -52,37 +51,19 @@ namespace Microsoft.AspNetCore.Rewrite
{
throw new ArgumentNullException(nameof(options));
}
-
+
if (reader == null)
{
throw new ArgumentNullException(nameof(reader));
}
- options.Rules.AddRange(new FileParser().Parse(reader));
+ var rules = new FileParser().Parse(reader);
+
+ foreach (var rule in rules)
+ {
+ options.Rules.Add(rule);
+ }
return options;
}
- ///
- /// Adds a mod_rewrite rule to the current rules.
- ///
- /// The UrlRewrite options.
- /// The literal string of a mod_rewrite rule:
- /// "RewriteRule Pattern Substitution [Flags]"
- public static RewriteOptions AddModRewriteRule(this RewriteOptions options, string rule)
- {
- if (options == null)
- {
- throw new ArgumentNullException(nameof(options));
- }
-
- if (rule == null)
- {
- throw new ArgumentNullException(nameof(rule));
- }
-
- var builder = new RuleBuilder();
- builder.AddRule(rule);
- options.Rules.Add(builder.Build());
- return options;
- }
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/RewriteExtensions.cs b/src/Microsoft.AspNetCore.Rewrite/RewriteBuilderExtensions.cs
similarity index 90%
rename from src/Microsoft.AspNetCore.Rewrite/RewriteExtensions.cs
rename to src/Microsoft.AspNetCore.Rewrite/RewriteBuilderExtensions.cs
index 50026ddc83..88d7676c30 100644
--- a/src/Microsoft.AspNetCore.Rewrite/RewriteExtensions.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/RewriteBuilderExtensions.cs
@@ -9,13 +9,13 @@ namespace Microsoft.AspNetCore.Builder
///
/// Extension methods for the
///
- public static class RewriteExtensions
+ public static class RewriteBuilderExtensions
{
///
/// Checks if a given Url matches rules and conditions, and modifies the HttpContext on match.
///
///
- /// Options for urlrewrite.
+ /// Options for rewrite.
///
public static IApplicationBuilder UseRewriter(this IApplicationBuilder app, RewriteOptions options)
{
diff --git a/src/Microsoft.AspNetCore.Rewrite/RewriteContext.cs b/src/Microsoft.AspNetCore.Rewrite/RewriteContext.cs
index be7108787d..4b4fb8e8db 100644
--- a/src/Microsoft.AspNetCore.Rewrite/RewriteContext.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/RewriteContext.cs
@@ -4,16 +4,19 @@
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
+using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Rewrite
{
///
- /// The UrlRewrite Context contains the HttpContext of the request and the file provider to check conditions.
+ /// The UrlRewrite Context contains the HttpContext of the request, the file provider, and the logger.
+ /// There is also a shared string builder across the application of rules.
///
public class RewriteContext
{
public HttpContext HttpContext { get; set; }
- public IFileProvider FileProvider { get; set; }
+ public IFileProvider StaticFileProvider { get; set; }
+ public ILogger Logger { get; set; }
// PERF: share the same string builder per request
internal StringBuilder Builder { get; set; } = new StringBuilder(64);
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/RewriteMiddleware.cs b/src/Microsoft.AspNetCore.Rewrite/RewriteMiddleware.cs
index 61c332b7c6..afcbcb576f 100644
--- a/src/Microsoft.AspNetCore.Rewrite/RewriteMiddleware.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/RewriteMiddleware.cs
@@ -6,7 +6,10 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Rewrite.Internal;
+using Microsoft.AspNetCore.Rewrite.Logging;
using Microsoft.Extensions.FileProviders;
+using Microsoft.Extensions.Logging;
+using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Rewrite
{
@@ -20,14 +23,20 @@ namespace Microsoft.AspNetCore.Rewrite
private readonly RequestDelegate _next;
private readonly RewriteOptions _options;
private readonly IFileProvider _fileProvider;
+ private readonly ILogger _logger;
///
/// Creates a new instance of
///
/// The delegate representing the next middleware in the request pipeline.
- /// The Hosting Environment.
+ /// The Hosting Environment.
+ /// The Logger Factory.
/// The middleware options, containing the rules to apply.
- public RewriteMiddleware(RequestDelegate next, IHostingEnvironment hostingEnv, RewriteOptions options)
+ public RewriteMiddleware(
+ RequestDelegate next,
+ IHostingEnvironment hostingEnvironment,
+ ILoggerFactory loggerFactory,
+ RewriteOptions options)
{
if (next == null)
{
@@ -41,7 +50,8 @@ namespace Microsoft.AspNetCore.Rewrite
_next = next;
_options = options;
- _fileProvider = _options.FileProvider ?? hostingEnv.WebRootFileProvider;
+ _fileProvider = _options.StaticFileProvider ?? hostingEnvironment.WebRootFileProvider;
+ _logger = loggerFactory.CreateLogger();
}
///
@@ -55,19 +65,27 @@ namespace Microsoft.AspNetCore.Rewrite
{
throw new ArgumentNullException(nameof(context));
}
- var urlContext = new RewriteContext { HttpContext = context, FileProvider = _fileProvider };
+ var urlContext = new RewriteContext {
+ HttpContext = context,
+ StaticFileProvider = _fileProvider,
+ Logger = _logger
+ };
+
foreach (var rule in _options.Rules)
{
- // Apply the rule
var result = rule.ApplyRule(urlContext);
switch (result.Result)
{
- case RuleTerminiation.Continue:
- // Explicitly show that we continue executing rules
+ case RuleTermination.Continue:
+ _logger.RewriteMiddlewareRequestContinueResults();
break;
- case RuleTerminiation.ResponseComplete:
+ case RuleTermination.ResponseComplete:
+ _logger.RewriteMiddlewareRequestResponseComplete(
+ urlContext.HttpContext.Response.Headers[HeaderNames.Location],
+ urlContext.HttpContext.Response.StatusCode);
return CompletedTask;
- case RuleTerminiation.StopRules:
+ case RuleTermination.StopRules:
+ _logger.RewriteMiddlewareRequestStopRules();
return _next(context);
default:
throw new ArgumentOutOfRangeException($"Invalid rule termination {result}");
diff --git a/src/Microsoft.AspNetCore.Rewrite/RewriteOptions.cs b/src/Microsoft.AspNetCore.Rewrite/RewriteOptions.cs
index 71eb2fef99..270c7a9313 100644
--- a/src/Microsoft.AspNetCore.Rewrite/RewriteOptions.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/RewriteOptions.cs
@@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
-using Microsoft.AspNetCore.Rewrite.Internal;
using Microsoft.Extensions.FileProviders;
namespace Microsoft.AspNetCore.Rewrite
@@ -12,10 +11,8 @@ namespace Microsoft.AspNetCore.Rewrite
///
public class RewriteOptions
{
- ///
- /// The ordered list of rules to apply to the context.
- ///
- public List Rules { get; set; } = new List();
- public IFileProvider FileProvider { get; set; }
+ // TODO doc comments
+ public IList Rules { get; } = new List();
+ public IFileProvider StaticFileProvider { get; set; }
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/RewriteOptionsExtensions.cs b/src/Microsoft.AspNetCore.Rewrite/RewriteOptionsExtensions.cs
new file mode 100644
index 0000000000..0861fa50f1
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Rewrite/RewriteOptionsExtensions.cs
@@ -0,0 +1,135 @@
+// 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 Microsoft.AspNetCore.Rewrite.Internal;
+using Microsoft.AspNetCore.Rewrite.Internal.CodeRules;
+using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite;
+
+namespace Microsoft.AspNetCore.Rewrite
+{
+ ///
+ /// The builder to a list of rules for and
+ ///
+ public static class RewriteOptionsExtensions
+ {
+ ///
+ /// Adds a rule to the current rules.
+ ///
+ /// The UrlRewrite options.
+ /// A rule to be added to the current rules.
+ /// The Rewrite options.
+ public static RewriteOptions Add(this RewriteOptions options, Rule rule)
+ {
+ options.Rules.Add(rule);
+ return options;
+ }
+
+ ///
+ /// Adds a rule to the current rules.
+ ///
+ /// The Rewrite options.
+ /// A Func that checks and applies the rule.
+ ///
+ public static RewriteOptions Add(this RewriteOptions options, Func applyRule)
+ {
+ options.Rules.Add(new DelegateRule(applyRule));
+ return options;
+ }
+
+ ///
+ /// Rewrites the path if the regex matches the HttpContext's PathString
+ ///
+ /// The Rewrite options.
+ /// The regex string to compare with.
+ /// If the regex matches, what to replace HttpContext with.
+ /// The Rewrite options.
+ public static RewriteOptions Rewrite(this RewriteOptions options, string regex, string urlPattern)
+ {
+ return Rewrite(options, regex, urlPattern, stopProcessing: false);
+ }
+
+ ///
+ /// Rewrites the path if the regex matches the HttpContext's PathString
+ ///
+ /// The Rewrite options.
+ /// The regex string to compare with.
+ /// If the regex matches, what to replace the uri with.
+ /// If the regex matches, conditionally stop processing other rules.
+ /// The Rewrite options.
+ public static RewriteOptions Rewrite(this RewriteOptions options, string regex, string urlPattern, bool stopProcessing)
+ {
+ var builder = new UrlRewriteRuleBuilder();
+ var pattern = new InputParser().ParseInputString(urlPattern);
+
+ builder.AddUrlMatch(regex);
+ builder.AddUrlAction(pattern, actionType: ActionType.Rewrite, stopProcessing: stopProcessing);
+ options.Rules.Add(builder.Build());
+ return options;
+ }
+
+ ///
+ /// Redirect the request if the regex matches the HttpContext's PathString
+ ///
+ /// The Rewrite options.
+ /// The regex string to compare with.
+ /// If the regex matches, what to replace the uri with.
+ /// The Rewrite options.
+ public static RewriteOptions Redirect(this RewriteOptions options, string regex, string urlPattern)
+ {
+ return Redirect(options, regex, urlPattern, statusCode: 302);
+ }
+
+ ///
+ /// Redirect the request if the regex matches the HttpContext's PathString
+ ///
+ /// The Rewrite options.
+ /// The regex string to compare with.
+ /// If the regex matches, what to replace the uri with.
+ /// The status code to add to the response.
+ /// The Rewrite options.
+ public static RewriteOptions Redirect(this RewriteOptions options, string regex, string urlPattern, int statusCode)
+ {
+ var builder = new UrlRewriteRuleBuilder();
+ var pattern = new InputParser().ParseInputString(urlPattern);
+
+ builder.AddUrlMatch(regex);
+ builder.AddUrlAction(pattern, actionType: ActionType.Redirect, stopProcessing: false);
+ options.Rules.Add(builder.Build());
+ return options;
+ }
+
+ // TODO 301 overload
+
+ ///
+ /// Redirect a request to https if the incoming request is http
+ ///
+ /// The Rewrite options.
+ public static RewriteOptions RedirectToHttps(this RewriteOptions options)
+ {
+ return RedirectToHttps(options, statusCode: 302, sslPort: null);
+ }
+
+ ///
+ /// Redirect a request to https if the incoming request is http
+ ///
+ /// The Rewrite options.
+ /// The status code to add to the response.
+ public static RewriteOptions RedirectToHttps(this RewriteOptions options, int statusCode)
+ {
+ return RedirectToHttps(options, statusCode, sslPort: null);
+ }
+
+ ///
+ /// Redirect a request to https if the incoming request is http
+ ///
+ /// The Rewrite options.
+ /// The status code to add to the response.
+ /// The SSL port to add to the response.
+ public static RewriteOptions RedirectToHttps(this RewriteOptions options, int statusCode, int? sslPort)
+ {
+ options.Rules.Add(new RedirectToHttpsRule { StatusCode = statusCode, SSLPort = sslPort });
+ return options;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/Rule.cs b/src/Microsoft.AspNetCore.Rewrite/Rule.cs
similarity index 78%
rename from src/Microsoft.AspNetCore.Rewrite/Internal/Rule.cs
rename to src/Microsoft.AspNetCore.Rewrite/Rule.cs
index 3ba6067f42..82a70dabc5 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/Rule.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/Rule.cs
@@ -1,8 +1,9 @@
// 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
+namespace Microsoft.AspNetCore.Rewrite
{
+ // make this public and doc comements
public abstract class Rule
{
public abstract RuleResult ApplyRule(RewriteContext context);
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/RuleResult.cs b/src/Microsoft.AspNetCore.Rewrite/RuleResult.cs
similarity index 64%
rename from src/Microsoft.AspNetCore.Rewrite/Internal/RuleResult.cs
rename to src/Microsoft.AspNetCore.Rewrite/RuleResult.cs
index f7b6c2b45b..2b2bb4abf3 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/RuleResult.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/RuleResult.cs
@@ -1,14 +1,14 @@
// 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
+namespace Microsoft.AspNetCore.Rewrite
{
public class RuleResult
{
- public static RuleResult Continue = new RuleResult { Result = RuleTerminiation.Continue };
- public static RuleResult ResponseComplete = new RuleResult { Result = RuleTerminiation.ResponseComplete };
- public static RuleResult StopRules = new RuleResult { Result = RuleTerminiation.StopRules };
+ public static RuleResult Continue = new RuleResult { Result = RuleTermination.Continue };
+ public static RuleResult ResponseComplete = new RuleResult { Result = RuleTermination.ResponseComplete };
+ public static RuleResult StopRules = new RuleResult { Result = RuleTermination.StopRules };
- public RuleTerminiation Result { get; set; }
+ public RuleTermination Result { get; set; }
}
}
diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/RuleTermination.cs b/src/Microsoft.AspNetCore.Rewrite/RuleTermination.cs
similarity index 75%
rename from src/Microsoft.AspNetCore.Rewrite/Internal/RuleTermination.cs
rename to src/Microsoft.AspNetCore.Rewrite/RuleTermination.cs
index 449a422944..dff816d9cc 100644
--- a/src/Microsoft.AspNetCore.Rewrite/Internal/RuleTermination.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/RuleTermination.cs
@@ -1,9 +1,9 @@
// 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
+namespace Microsoft.AspNetCore.Rewrite
{
- public enum RuleTerminiation
+ public enum RuleTermination
{
Continue,
ResponseComplete,
diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewriteExtensions.cs b/src/Microsoft.AspNetCore.Rewrite/UrlRewriteOptionsExtensions.cs
similarity index 68%
rename from src/Microsoft.AspNetCore.Rewrite/UrlRewriteExtensions.cs
rename to src/Microsoft.AspNetCore.Rewrite/UrlRewriteOptionsExtensions.cs
index fb362718a5..1ca090fdbe 100644
--- a/src/Microsoft.AspNetCore.Rewrite/UrlRewriteExtensions.cs
+++ b/src/Microsoft.AspNetCore.Rewrite/UrlRewriteOptionsExtensions.cs
@@ -8,24 +8,24 @@ using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite;
namespace Microsoft.AspNetCore.Rewrite
{
- public static class UrlRewriteExtensions
+ public static class UrlRewriteOptionsExtensions
{
///
/// Imports rules from a mod_rewrite file and adds the rules to current rules.
///
/// The UrlRewrite options.
- ///
+ ///
/// The path to the file containing urlrewrite rules.
- public static RewriteOptions ImportFromUrlRewrite(this RewriteOptions options, IHostingEnvironment hostingEnv, string filePath)
+ public static RewriteOptions ImportFromUrlRewrite(this RewriteOptions options, IHostingEnvironment hostingEnvironment, string filePath)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
- if (hostingEnv == null)
+ if (hostingEnvironment == null)
{
- throw new ArgumentNullException(nameof(hostingEnv));
+ throw new ArgumentNullException(nameof(hostingEnvironment));
}
if (string.IsNullOrEmpty(filePath))
@@ -33,35 +33,36 @@ namespace Microsoft.AspNetCore.Rewrite
throw new ArgumentException(nameof(filePath));
}
- var path = Path.Combine(hostingEnv.ContentRootPath, filePath);
+ var path = Path.Combine(hostingEnvironment.ContentRootPath, filePath);
using (var stream = File.OpenRead(path))
{
- options.Rules.AddRange(new FileParser().Parse(new StreamReader(stream)));
- };
- return options;
+ return ImportFromUrlRewrite(options, new StreamReader(stream));
+ }
}
///
/// Imports rules from a mod_rewrite file and adds the rules to current rules.
///
/// The UrlRewrite options.
- /// The text reader stream.
- public static RewriteOptions ImportFromUrlRewrite(this RewriteOptions options, TextReader stream)
+ /// The text reader stream.
+ public static RewriteOptions ImportFromUrlRewrite(this RewriteOptions options, TextReader reader)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
- if (stream == null)
+ if (reader == null)
{
- throw new ArgumentException(nameof(stream));
+ throw new ArgumentException(nameof(reader));
}
- using (stream)
+ var rules = new UrlRewriteFileParser().Parse(reader);
+
+ foreach (var rule in rules)
{
- options.Rules.AddRange(new FileParser().Parse(stream));
- };
+ options.Rules.Add(rule);
+ }
return options;
}
}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/CodeRules/MiddlewareTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/CodeRules/MiddlewareTests.cs
index 1f08becb6c..ce73843067 100644
--- a/test/Microsoft.AspNetCore.Rewrite.Tests/CodeRules/MiddlewareTests.cs
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/CodeRules/MiddlewareTests.cs
@@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.CodeRules
[Fact]
public async Task CheckRewritePath()
{
- var options = new RewriteOptions().RewriteRule("(.*)", "http://example.com/{R:1}");
+ var options = new RewriteOptions().Rewrite("(.*)", "http://example.com/{R:1}");
var builder = new WebHostBuilder()
.Configure(app =>
{
@@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.CodeRules
[Fact]
public async Task CheckRedirectPath()
{
- var options = new RewriteOptions().RedirectRule("(.*)","http://example.com/{R:1}", statusCode: 301);
+ var options = new RewriteOptions().Redirect("(.*)","http://example.com/{R:1}", statusCode: 301);
var builder = new WebHostBuilder()
.Configure(app =>
{
@@ -52,25 +52,6 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.CodeRules
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()
{
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ModRewriteMiddlewareTest.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ModRewriteMiddlewareTest.cs
index 62903412d5..7b358c265f 100644
--- a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ModRewriteMiddlewareTest.cs
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ModRewriteMiddlewareTest.cs
@@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
[Fact]
public async Task Invoke_RewritePathWhenMatching()
{
- var options = new RewriteOptions().AddModRewriteRule("RewriteRule /hey/(.*) /$1 ");
+ var options = new RewriteOptions().ImportFromModRewrite(new StringReader("RewriteRule /hey/(.*) /$1 "));
var builder = new WebHostBuilder()
.Configure(app =>
{
@@ -34,8 +34,8 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
[Fact]
public async Task Invoke_RewritePathTerminatesOnFirstSuccessOfRule()
{
- var options = new RewriteOptions().AddModRewriteRule("RewriteRule /hey/(.*) /$1 [L]")
- .AddModRewriteRule("RewriteRule /hello /what");
+ var options = new RewriteOptions().ImportFromModRewrite(new StringReader("RewriteRule /hey/(.*) /$1 [L]"))
+ .ImportFromModRewrite(new StringReader("RewriteRule /hello /what"));
var builder = new WebHostBuilder()
.Configure(app =>
{
@@ -52,8 +52,8 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
[Fact]
public async Task Invoke_RewritePathDoesNotTerminateOnFirstSuccessOfRule()
{
- var options = new RewriteOptions().AddModRewriteRule("RewriteRule /hey/(.*) /$1")
- .AddModRewriteRule("RewriteRule /hello /what");
+ var options = new RewriteOptions().ImportFromModRewrite(new StringReader("RewriteRule /hey/(.*) /$1"))
+ .ImportFromModRewrite(new StringReader("RewriteRule /hello /what"));
var builder = new WebHostBuilder()
.Configure(app =>
{
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/TestStringParserTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/TestStringParserTests.cs
index a362137d10..b07dcdd7c6 100644
--- a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/TestStringParserTests.cs
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/TestStringParserTests.cs
@@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite;
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
using Xunit;
-namespace Microsoft.AspNetCore.Rewrite
+namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
{
public class TestStringParserTests
{
@@ -119,7 +119,7 @@ namespace Microsoft.AspNetCore.Rewrite
[InlineData(@"%a", "Cannot parse '%a' to integer at string index: '1'")] // invalid character after %
[InlineData(@"$a", "Cannot parse '$a' to integer at string index: '1'")] // invalid character after $
[InlineData(@"%{asdf", "Missing close brace for parameter at string index: '6'")] // no closing } with characters
- public void ConditionParser_Bad(string testString, string expected)
+ public void ConditionParser_InvalidInput(string testString, string expected)
{
var ex = Assert.Throws(() => new TestStringParser().Parse(testString));
Assert.Equal(ex.Message, expected);
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ConditionMatchSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ConditionMatchSegmentTests.cs
new file mode 100644
index 0000000000..51208cbba5
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ConditionMatchSegmentTests.cs
@@ -0,0 +1,37 @@
+// 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;
+using Microsoft.AspNetCore.Rewrite.Internal;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class ConditionMatchSegmentTests
+ {
+
+ [Theory]
+ [InlineData(1, "foo")]
+ [InlineData(2, "bar")]
+ [InlineData(3, "baz")]
+ public void ConditionMatch_AssertBackreferencesObtainsCorrectValue(int index, string expected)
+ {
+ // Arrange
+ var condMatch = CreateTestMatch();
+ var segment = new ConditionMatchSegment(index);
+
+ // Act
+ var results = segment.Evaluate(null, null, condMatch);
+
+ // Assert
+ Assert.Equal(expected, results);
+ }
+
+ private static MatchResults CreateTestMatch()
+ {
+ var match = Regex.Match("foo/bar/baz", "(.*)/(.*)/(.*)");
+ return new MatchResults {BackReference = match.Groups, Success = match.Success};
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/DateTimeSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/DateTimeSegmentTests.cs
new file mode 100644
index 0000000000..9e478da8e4
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/DateTimeSegmentTests.cs
@@ -0,0 +1,44 @@
+// 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 Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class DateTimeSegmentTests
+ {
+ [Theory]
+ [InlineData("TIME_YEAR")]
+ [InlineData("TIME_MON")]
+ [InlineData("TIME_DAY")]
+ [InlineData("TIME_HOUR")]
+ [InlineData("TIME_MIN")]
+ [InlineData("TIME_SEC")]
+ [InlineData("TIME_WDAY")]
+ [InlineData("TIME")]
+ public void DateTime_AssertDoesntThrowOnCheckOfSegment(string input)
+ {
+ // Arrange
+ var segment = new DateTimeSegment(input);
+
+ // Act
+ var results = segment.Evaluate(null, null, null);
+
+ // TODO testing dates is hard, could use moq
+ // currently just assert that the segment doesn't throw.
+ }
+
+ [Theory]
+ [InlineData("foo", "Unsupported segment: 'foo'")]
+ [InlineData("wow", "Unsupported segment: 'wow'")]
+ public void DateTime_AssertThrowsOnInvalidInput(string input, string expected)
+ {
+
+ // Act And Assert
+ var ex = Assert.Throws(() => new DateTimeSegment(input));
+ Assert.Equal(ex.Message, expected);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/HeaderSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/HeaderSegmentTests.cs
new file mode 100644
index 0000000000..b8472929b7
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/HeaderSegmentTests.cs
@@ -0,0 +1,43 @@
+// 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 Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Microsoft.Net.Http.Headers;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class HeaderSegmentTests
+ {
+ [Fact]
+ public void HeaderSegment_AssertGettingWithHeaderReturnsCorrectValue()
+ {
+ // Arrange
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+
+ context.HttpContext.Request.Headers[HeaderNames.Location] = "foo";
+ var segment = new HeaderSegment(HeaderNames.Location);
+
+ // Act
+ var results = segment.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("foo", results);
+ }
+
+ [Fact]
+ public void HeaderSegment_AssertGettingANonExistantHeaderReturnsNull()
+ {
+ // Arrange
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ var segment = new HeaderSegment(HeaderNames.Location);
+
+ // Act
+ var results = segment.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Null(results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsHttpsModSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsHttpsModSegmentTests.cs
new file mode 100644
index 0000000000..323f3198b4
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsHttpsModSegmentTests.cs
@@ -0,0 +1,30 @@
+// 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 Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class IsHttpsModSegmentTests
+ {
+ [Theory]
+ [InlineData("http", "off")]
+ [InlineData("https", "on")]
+ public void IsHttps_AssertCorrectBehaviorWhenProvidedHttpContext(string input, string expected)
+ {
+ // Arrange
+ var segement = new IsHttpsModSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Request.Scheme = input;
+
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal(expected, results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsHttpsSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsHttpsSegmentTests.cs
new file mode 100644
index 0000000000..c3d3b6eccc
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsHttpsSegmentTests.cs
@@ -0,0 +1,30 @@
+// 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 Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class IsHttpsSegmentTests
+ {
+ [Theory]
+ [InlineData("http", "OFF")]
+ [InlineData("https", "ON")]
+ public void IsHttps_AssertCorrectBehaviorWhenProvidedHttpContext(string input, string expected)
+ {
+ // Arrange
+ var segement = new IsHttpsSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Request.Scheme = input;
+
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal(expected, results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsIPV6SegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsIPV6SegmentTests.cs
new file mode 100644
index 0000000000..c787998e9c
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsIPV6SegmentTests.cs
@@ -0,0 +1,59 @@
+// 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.Net;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class IsIPV6SegmentTests
+ {
+ [Fact]
+ public void IsIPv6_AssertNullRemoteIpAddressReportsCorrectValue()
+ {
+ // Arrange
+ var segement = new IsIPV6Segment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Connection.RemoteIpAddress = null;
+
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("off", results);
+ }
+
+ [Fact]
+ public void IsIPv6_AssertCorrectBehaviorWhenIPv6IsUsed()
+ {
+ // Arrange
+ var segement = new IsIPV6Segment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Connection.RemoteIpAddress = IPAddress.Parse("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
+
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("on", results);
+ }
+
+ [Fact]
+ public void IsIPv6_AssertCorrectBehaviorWhenIPv4IsUsed()
+ {
+ // Arrange
+ var segement = new IsIPV6Segment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Connection.RemoteIpAddress = IPAddress.Parse("20.30.40.50");
+
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("off", results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LIteralSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LIteralSegmentTests.cs
new file mode 100644
index 0000000000..1bf3e74fee
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LIteralSegmentTests.cs
@@ -0,0 +1,24 @@
+// 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 Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class LiteralSegmentTests
+ {
+ [Fact]
+ public void LiteralSegment_AssertSegmentIsCorrect()
+ {
+ // Arrange
+ var segement = new LiteralSegment("foo");
+
+ // Act
+ var results = segement.Evaluate(null, null, null);
+
+ // Assert
+ Assert.Equal("foo", results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LocalAddressSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LocalAddressSegmentTests.cs
new file mode 100644
index 0000000000..07d7254574
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LocalAddressSegmentTests.cs
@@ -0,0 +1,41 @@
+// 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.Net;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class LocalAddressSegmentTests
+ {
+ [Fact]
+ public void LocalAddress_AssertSegmentIsCorrect()
+ {
+ // Arrange
+ var segement = new LocalAddressSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Connection.LocalIpAddress = IPAddress.Parse("20.30.40.50");
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("20.30.40.50", results);
+ }
+
+ [Fact]
+ public void LocalAddress_AssertNullLocalIpAddressReturnsNull()
+ {
+ var segement = new LocalAddressSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Connection.LocalIpAddress = null;
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Null( results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LocalPortSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LocalPortSegmentTests.cs
new file mode 100644
index 0000000000..1a3dad1896
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LocalPortSegmentTests.cs
@@ -0,0 +1,28 @@
+// 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.Globalization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class LocalPortSegmentTests
+ {
+ [Fact]
+ public void LocalPortSegment_AssertSegmentIsCorrect()
+ {
+ // Arrange
+ var segement = new LocalPortSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Connection.LocalPort = 800;
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("800", results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/QueryStringSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/QueryStringSegmentTests.cs
new file mode 100644
index 0000000000..a02986fc16
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/QueryStringSegmentTests.cs
@@ -0,0 +1,27 @@
+// 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 Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class QueryStringSegmentTests
+ {
+ [Fact]
+ public void QueryString_AssertSegmentIsCorrect()
+ {
+ // Arrange
+ var segement = new QueryStringSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Request.QueryString = new QueryString("?hey=1");
+
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("?hey=1", results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RemoteAddressSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RemoteAddressSegmentTests.cs
new file mode 100644
index 0000000000..c7f5ede0dc
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RemoteAddressSegmentTests.cs
@@ -0,0 +1,40 @@
+// 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.Net;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class RemoteAddressSegmentTests
+ {
+ [Fact]
+ public void RemoteAddress_AssertSegmentIsCorrect()
+ {
+ // Arrange
+ var segement = new RemoteAddressSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Connection.RemoteIpAddress = IPAddress.Parse("20.30.40.50");
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("20.30.40.50", results);
+ }
+
+ [Fact]
+ public void RemoteAddress_AssertNullLocalIpAddressReturnsNull()
+ {
+ var segement = new RemoteAddressSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Connection.RemoteIpAddress = null;
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Null(results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RemotePortSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RemotePortSegmentTests.cs
new file mode 100644
index 0000000000..6980e2379f
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RemotePortSegmentTests.cs
@@ -0,0 +1,26 @@
+// 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 Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class RemotePortSegmentTests
+ {
+ [Fact]
+ public void RemotePort_AssertSegmentIsCorrect()
+ {
+ // Arrange
+ var segement = new RemotePortSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Connection.RemotePort = 800;
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("800", results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RequestFilenameSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RequestFilenameSegmentTests.cs
new file mode 100644
index 0000000000..16e051d7af
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RequestFilenameSegmentTests.cs
@@ -0,0 +1,26 @@
+// 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 Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class RequestFilenameSegmentTests
+ {
+ [Fact]
+ public void RequestFilename_AssertSegmentIsCorrect()
+ {
+ // Arrange
+ var segement = new RequestFileNameSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Request.Path = new PathString("/foo/bar");
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("/foo/bar", results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RequestMethodSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RequestMethodSegmentTests.cs
new file mode 100644
index 0000000000..fc9ac14b01
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RequestMethodSegmentTests.cs
@@ -0,0 +1,26 @@
+// 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 Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class RequestMethodSegmentTests
+ {
+ [Fact]
+ public void RequestMethod_AssertSegmentIsCorrect()
+ {
+ // Arrange
+ var segement = new RequestMethodSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Request.Method = "GET";
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("GET", results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RuleMatchSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RuleMatchSegmentTests.cs
new file mode 100644
index 0000000000..8e4d8ccfc4
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RuleMatchSegmentTests.cs
@@ -0,0 +1,36 @@
+// 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;
+using Microsoft.AspNetCore.Rewrite.Internal;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class RuleMatchSegmentTests
+ {
+ [Theory]
+ [InlineData(1, "foo")]
+ [InlineData(2, "bar")]
+ [InlineData(3, "baz")]
+ public void RuleMatch_AssertBackreferencesObtainsCorrectValue(int index, string expected)
+ {
+ // Arrange
+ var ruleMatch = CreateTestMatch();
+ var segment = new RuleMatchSegment(index);
+
+ // Act
+ var results = segment.Evaluate(null, ruleMatch, null);
+
+ // Assert
+ Assert.Equal(expected, results);
+ }
+
+ private static MatchResults CreateTestMatch()
+ {
+ var match = Regex.Match("foo/bar/baz", "(.*)/(.*)/(.*)");
+ return new MatchResults { BackReference = match.Groups, Success = match.Success };
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/SchemeSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/SchemeSegmentTests.cs
new file mode 100644
index 0000000000..3caac305c6
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/SchemeSegmentTests.cs
@@ -0,0 +1,26 @@
+// 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 Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class SchemeSegmentTests
+ {
+ [Fact]
+ public void SchemeSegment_AssertSegmentIsCorrect()
+ {
+ // Arrange
+ var segement = new SchemeSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Request.Scheme = "http";
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("http", results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ServerProtocolSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ServerProtocolSegmentTests.cs
new file mode 100644
index 0000000000..9128ef6b32
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ServerProtocolSegmentTests.cs
@@ -0,0 +1,28 @@
+// 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 Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Features;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class ServerProtocolSegmentTests
+ {
+ [Fact]
+ public void ServerProtocol_AssertSegmentIsCorrect()
+ {
+ // Arrange
+ var segement = new ServerProtocolSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Features.Set(new HttpRequestFeature { Protocol = "http" });
+
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("http", results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ToLowerSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ToLowerSegmentTests.cs
new file mode 100644
index 0000000000..a6b434ff3d
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ToLowerSegmentTests.cs
@@ -0,0 +1,32 @@
+// 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.Collections.Generic;
+using Microsoft.AspNetCore.Rewrite.Internal;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class ToLowerSegmentTests
+ {
+ [Theory]
+ [InlineData("Hello", "hello")]
+ [InlineData("WHAT", "what")]
+ [InlineData("hey", "hey")]
+ public void ToLower_AssertLowerCaseWorksAppropriately(string input, string expected)
+ {
+ // Arrange
+ var pattern = new Pattern(new List());
+ pattern.PatternSegments.Add(new LiteralSegment(input));
+ var segement = new ToLowerSegment(pattern);
+ var context = new RewriteContext();
+
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal(expected, results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/UrlEncodeSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/UrlEncodeSegmentTests.cs
new file mode 100644
index 0000000000..767876a9a5
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/UrlEncodeSegmentTests.cs
@@ -0,0 +1,32 @@
+// 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.Collections.Generic;
+using Microsoft.AspNetCore.Rewrite.Internal;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class UrlEncodeSegmentTests
+ {
+ [Theory]
+ [InlineData(" ", "%20")]
+ [InlineData("x&y", "x%26y")]
+ [InlineData("hey", "hey")]
+ public void ToLower_AssertLowerCaseWorksAppropriately(string input, string expected)
+ {
+ // Arrange
+ var pattern = new Pattern(new List());
+ pattern.PatternSegments.Add(new LiteralSegment(input));
+ var segement = new UrlEncodeSegment(pattern);
+ var context = new RewriteContext();
+
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal(expected, results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/UrlSegmentTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/UrlSegmentTests.cs
new file mode 100644
index 0000000000..d23c2a5fb4
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/UrlSegmentTests.cs
@@ -0,0 +1,26 @@
+// 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 Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
+{
+ public class UrlSegmentTests
+ {
+ [Fact]
+ public void LocalPortSegment_AssertSegmentIsCorrect()
+ {
+ // Arrange
+ var segement = new UrlSegment();
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ context.HttpContext.Request.Path = new PathString("/foo/bar");
+ // Act
+ var results = segement.Evaluate(context, null, null);
+
+ // Assert
+ Assert.Equal("/foo/bar", results);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlActions/ForbiddenActionTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlActions/ForbiddenActionTests.cs
new file mode 100644
index 0000000000..27e2bcca40
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlActions/ForbiddenActionTests.cs
@@ -0,0 +1,28 @@
+// 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 Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal;
+using Microsoft.AspNetCore.Rewrite.Internal.UrlActions;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.UrlActions
+{
+ public class ForbiddenActionTests
+ {
+ [Fact]
+ public void Forbidden_Verify403IsInStatusCode()
+ {
+ // Arrange
+ var context = new RewriteContext {HttpContext = new DefaultHttpContext()};
+ var action = new ForbiddenAction();
+
+ // Act
+ var results = action.ApplyAction(context, null, null);
+
+ // Assert
+ Assert.Equal(results.Result, RuleTermination.ResponseComplete);
+ Assert.Equal(context.HttpContext.Response.StatusCode, StatusCodes.Status403Forbidden);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlActions/GoneActionTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlActions/GoneActionTests.cs
new file mode 100644
index 0000000000..1daccb17f2
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlActions/GoneActionTests.cs
@@ -0,0 +1,28 @@
+// 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 Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite.Internal;
+using Microsoft.AspNetCore.Rewrite.Internal.UrlActions;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.UrlActions
+{
+ public class GoneActionTests
+ {
+ [Fact]
+ public void Gone_Verify410IsInStatusCode()
+ {
+ // Arrange
+ var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
+ var action = new GoneAction();
+
+ // Act
+ var results = action.ApplyAction(context, null, null);
+
+ // Assert
+ Assert.Equal(results.Result, RuleTermination.ResponseComplete);
+ Assert.Equal(context.HttpContext.Response.StatusCode, StatusCodes.Status410Gone);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FileParserTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FileParserTests.cs
index 2c45fa8f02..43a8bac189 100644
--- a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FileParserTests.cs
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FileParserTests.cs
@@ -29,13 +29,13 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
var expected = new List();
expected.Add(CreateTestRule(new List(),
- Url: "^article/([0-9]+)/([_0-9a-z-]+)",
+ url: "^article/([0-9]+)/([_0-9a-z-]+)",
name: "Rewrite to article.aspx",
actionType: ActionType.Rewrite,
pattern: "article.aspx?id={R:1}&title={R:2}"));
// act
- var res = new FileParser().Parse(new StringReader(xml));
+ var res = new UrlRewriteFileParser().Parse(new StringReader(xml));
// assert
AssertUrlRewriteRuleEquality(res, expected);
@@ -66,13 +66,13 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
var expected = new List();
expected.Add(CreateTestRule(condList,
- Url: "^article/([0-9]+)/([_0-9a-z-]+)",
+ url: "^article/([0-9]+)/([_0-9a-z-]+)",
name: "Rewrite to article.aspx",
actionType: ActionType.Rewrite,
pattern: "article.aspx?id={R:1}&title={R:2}"));
// act
- var res = new FileParser().Parse(new StringReader(xml));
+ var res = new UrlRewriteFileParser().Parse(new StringReader(xml));
// assert
AssertUrlRewriteRuleEquality(res, expected);
@@ -110,18 +110,18 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
var expected = new List();
expected.Add(CreateTestRule(condList,
- Url: "^article/([0-9]+)/([_0-9a-z-]+)",
+ url: "^article/([0-9]+)/([_0-9a-z-]+)",
name: "Rewrite to article.aspx",
actionType: ActionType.Rewrite,
pattern: "article.aspx?id={R:1}&title={R:2}"));
expected.Add(CreateTestRule(condList,
- Url: "^article/([0-9]+)/([_0-9a-z-]+)",
+ url: "^article/([0-9]+)/([_0-9a-z-]+)",
name: "Rewrite to another article.aspx",
actionType: ActionType.Rewrite,
pattern: "article.aspx?id={R:1}&title={R:2}"));
// act
- var res = new FileParser().Parse(new StringReader(xml));
+ var res = new UrlRewriteFileParser().Parse(new StringReader(xml));
// assert
AssertUrlRewriteRuleEquality(res, expected);
@@ -135,7 +135,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
bool enabled = true,
PatternSyntax patternSyntax = PatternSyntax.ECMAScript,
bool stopProcessing = false,
- string Url = "",
+ string url = "",
bool ignoreCase = true,
bool negate = false,
ActionType actionType = ActionType.None,
@@ -145,22 +145,12 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
RedirectType redirectType = RedirectType.Permanent
)
{
- return new UrlRewriteRule
- {
- Action = new RewriteAction(RuleTerminiation.Continue, new InputParser().ParseInputString(Url), clearQuery: false),
- Name = name,
- Enabled = enabled,
- InitialMatch = new RegexMatch(new Regex("^OFF$"), false)
- {
- },
- Conditions = new Conditions
- {
- ConditionList = conditions
- }
- };
+ return new UrlRewriteRule(name, new RegexMatch(new Regex("^OFF$"), false), conditions,
+ new RewriteAction(RuleTermination.Continue, new InputParser().ParseInputString(url), clearQuery: false));
}
- private void AssertUrlRewriteRuleEquality(List actual, List expected)
+ // TODO make rules comparable?
+ private void AssertUrlRewriteRuleEquality(IList actual, IList expected)
{
Assert.Equal(actual.Count, expected.Count);
for (var i = 0; i < actual.Count; i++)
@@ -169,23 +159,22 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
var r2 = expected[i];
Assert.Equal(r1.Name, r2.Name);
- Assert.Equal(r1.Enabled, r2.Enabled);
if (r1.Conditions == null)
{
- Assert.Equal(r2.Conditions.ConditionList.Count, 0);
+ Assert.Equal(r2.Conditions.Count, 0);
}
else if (r2.Conditions == null)
{
- Assert.Equal(r1.Conditions.ConditionList.Count, 0);
+ Assert.Equal(r1.Conditions.Count, 0);
}
else
{
- Assert.Equal(r1.Conditions.ConditionList.Count, r2.Conditions.ConditionList.Count);
- for (var j = 0; j < r1.Conditions.ConditionList.Count; j++)
+ Assert.Equal(r1.Conditions.Count, r2.Conditions.Count);
+ for (var j = 0; j < r1.Conditions.Count; j++)
{
- var c1 = r1.Conditions.ConditionList[j];
- var c2 = r2.Conditions.ConditionList[j];
+ var c1 = r1.Conditions[j];
+ var c2 = r2.Conditions[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 b1e0a6f45b..db70d69e4a 100644
--- a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FormatExceptionHandlingTests.cs
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FormatExceptionHandlingTests.cs
@@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
public void ThrowFormatExceptionWithCorrectMessage(string input, string expected)
{
// Arrange, Act, Assert
- var ex = Assert.Throws(() => new FileParser().Parse(new StringReader(input)));
+ var ex = Assert.Throws(() => new UrlRewriteFileParser().Parse(new StringReader(input)));
Assert.Equal(ex.Message, expected);
}
}
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/InputParserTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/InputParserTests.cs
index 0a69cdf8ad..0f4b2ba7fb 100644
--- a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/InputParserTests.cs
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/InputParserTests.cs
@@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
{
var context = new DefaultHttpContext();
- return new RewriteContext { HttpContext = context, FileProvider = null };
+ return new RewriteContext { HttpContext = context, StaticFileProvider = null };
}
private MatchResults CreateTestRuleMatch()
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/MiddleWareTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/MiddleWareTests.cs
index f2018d20b9..eadddbd60d 100644
--- a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/MiddleWareTests.cs
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/MiddleWareTests.cs
@@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
var response = await server.CreateClient().GetAsync("article/10/hey");
- Assert.Equal(response.Headers.Location.OriginalString, "article.aspx?id=10&title=hey");
+ Assert.Equal(response.Headers.Location.OriginalString, "/article.aspx?id=10&title=hey");
}
[Fact]
@@ -112,7 +112,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
var response = await server.CreateClient().GetAsync("HElLo");
- Assert.Equal(response.Headers.Location.OriginalString, "hello");
+ Assert.Equal(response.Headers.Location.OriginalString, "/hello");
}
[Fact]
@@ -139,7 +139,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
var response = await server.CreateClient().GetAsync("hey/hello/");
- Assert.Equal(response.Headers.Location.OriginalString, "hey/hello");
+ Assert.Equal(response.Headers.Location.OriginalString, "/hey/hello");
}
[Fact]
@@ -166,7 +166,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
var response = await server.CreateClient().GetAsync("hey/hello");
- Assert.Equal(response.Headers.Location.OriginalString, "hey/hello/");
+ Assert.Equal(response.Headers.Location.OriginalString, "/hey/hello/");
}
[Fact]
diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/UrlRewriteApplicationTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/UrlRewriteApplicationTests.cs
index 6c5abfedb5..6d6864d398 100644
--- a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/UrlRewriteApplicationTests.cs
+++ b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/UrlRewriteApplicationTests.cs
@@ -1,15 +1,10 @@
// 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.IO;
using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Rewrite.Internal;
using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite;
-using Microsoft.AspNetCore.TestHost;
using Xunit;
namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
@@ -28,11 +23,11 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
");
- var rules = new FileParser().Parse(xml);
+ var rules = new UrlRewriteFileParser().Parse(xml);
Assert.Equal(rules.Count, 1);
var ruleResults = rules.FirstOrDefault().ApplyRule(new RewriteContext {HttpContext = new DefaultHttpContext()});
- Assert.Equal(ruleResults.Result, RuleTerminiation.StopRules);
+ Assert.Equal(ruleResults.Result, RuleTermination.StopRules);
}
[Fact]
@@ -46,11 +41,11 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
");
- var rules = new FileParser().Parse(xml);
+ var rules = new UrlRewriteFileParser().Parse(xml);
Assert.Equal(rules.Count, 1);
var ruleResults = rules.FirstOrDefault().ApplyRule(new RewriteContext { HttpContext = new DefaultHttpContext() });
- Assert.Equal(ruleResults.Result, RuleTerminiation.Continue);
+ Assert.Equal(ruleResults.Result, RuleTermination.Continue);
}
}
}