General bugfixes and style cleanup
This commit is contained in:
parent
74b0b7945d
commit
0cb7445921
|
|
@ -37,7 +37,7 @@ namespace RewriteSample
|
||||||
return RuleResult.Continue;
|
return RuleResult.Continue;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
app.Run(context => context.Response.WriteAsync(context.Request.Path));
|
app.Run(context => context.Response.WriteAsync($"Rewritten Url: {context.Request.Path + context.Request.QueryString}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ namespace Microsoft.AspNetCore.Rewrite
|
||||||
|
|
||||||
public static RewriteOptions RewriteToHttps(this RewriteOptions options, int? sslPort, bool stopProcessing)
|
public static RewriteOptions RewriteToHttps(this RewriteOptions options, int? sslPort, bool stopProcessing)
|
||||||
{
|
{
|
||||||
options.Rules.Add(new RewriteToHttpsRule {SSLPort = sslPort, stopProcessing = stopProcessing });
|
options.Rules.Add(new RewriteToHttpsRule {SSLPort = sslPort, StopProcessing = stopProcessing });
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.CodeRules
|
||||||
{
|
{
|
||||||
public class RewriteToHttpsRule : Rule
|
public class RewriteToHttpsRule : Rule
|
||||||
{
|
{
|
||||||
public bool stopProcessing { get; set; }
|
public bool StopProcessing { get; set; }
|
||||||
public int? SSLPort { get; set; }
|
public int? SSLPort { get; set; }
|
||||||
|
|
||||||
public override RuleResult ApplyRule(RewriteContext context)
|
public override RuleResult ApplyRule(RewriteContext context)
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.CodeRules
|
||||||
|
|
||||||
context.HttpContext.Request.Scheme = "https";
|
context.HttpContext.Request.Scheme = "https";
|
||||||
context.HttpContext.Request.Host = host;
|
context.HttpContext.Request.Host = host;
|
||||||
return stopProcessing ? RuleResult.StopRules: RuleResult.Continue;
|
return StopProcessing ? RuleResult.StopRules: RuleResult.Continue;
|
||||||
}
|
}
|
||||||
return RuleResult.Continue;
|
return RuleResult.Continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,19 +172,16 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
||||||
case 'g':
|
case 'g':
|
||||||
if (!context.Next())
|
if (!context.Next())
|
||||||
{
|
{
|
||||||
throw new FormatException(context.Error());
|
throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(context.Template, context.Index));
|
||||||
}
|
}
|
||||||
if (context.Current == 't')
|
switch (context.Current)
|
||||||
{
|
{
|
||||||
return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.Greater, operand: null);
|
case 't':
|
||||||
}
|
return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.Greater, operand: null);
|
||||||
else if (context.Current == 'e')
|
case 'e':
|
||||||
{
|
return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.GreaterEqual, operand: null);
|
||||||
return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.GreaterEqual, operand: null);
|
default:
|
||||||
}
|
throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(context.Template, context.Index));
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new FormatException(context.Error());
|
|
||||||
}
|
}
|
||||||
case 'l':
|
case 'l':
|
||||||
// name conflict with -l and -lt/-le, so the assumption is if there is no
|
// name conflict with -l and -lt/-le, so the assumption is if there is no
|
||||||
|
|
@ -193,17 +190,14 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
||||||
{
|
{
|
||||||
return new ParsedModRewriteInput(invert, ConditionType.PropertyTest, OperationType.SymbolicLink, operand: null);
|
return new ParsedModRewriteInput(invert, ConditionType.PropertyTest, OperationType.SymbolicLink, operand: null);
|
||||||
}
|
}
|
||||||
if (context.Current == 't')
|
switch (context.Current)
|
||||||
{
|
{
|
||||||
return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.Less, operand: null);
|
case 't':
|
||||||
}
|
return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.Less, operand: null);
|
||||||
else if (context.Current == 'e')
|
case 'e':
|
||||||
{
|
return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.LessEqual, operand: null);
|
||||||
return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.LessEqual, operand: null);
|
default:
|
||||||
}
|
throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(context.Template, context.Index));
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(context.Template, context.Index));
|
|
||||||
}
|
}
|
||||||
case 'n':
|
case 'n':
|
||||||
if (!context.Next() || context.Current != 'e')
|
if (!context.Next() || context.Current != 'e')
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
||||||
{
|
{
|
||||||
public List<Rule> Parse(TextReader input)
|
public List<Rule> Parse(TextReader input)
|
||||||
{
|
{
|
||||||
string line = null;
|
string line;
|
||||||
var rules = new List<Rule>();
|
var rules = new List<Rule>();
|
||||||
var builder = new RuleBuilder();
|
var builder = new RuleBuilder();
|
||||||
var lineNum = 0;
|
var lineNum = 0;
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
||||||
// Invalid syntax to have any spaces.
|
// Invalid syntax to have any spaces.
|
||||||
var tokens = flagString.Substring(1, flagString.Length - 2).Split(',');
|
var tokens = flagString.Substring(1, flagString.Length - 2).Split(',');
|
||||||
var flags = new Flags();
|
var flags = new Flags();
|
||||||
foreach (string token in tokens)
|
foreach (var token in tokens)
|
||||||
{
|
{
|
||||||
var hasPayload = token.Split('=');
|
var hasPayload = token.Split('=');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Extensions;
|
using Microsoft.AspNetCore.Http.Extensions;
|
||||||
|
|
||||||
|
|
@ -33,9 +34,9 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
||||||
var pattern = Url.Evaluate(context, ruleMatch, condMatch);
|
var pattern = Url.Evaluate(context, ruleMatch, condMatch);
|
||||||
|
|
||||||
// TODO PERF, substrings, object creation, etc.
|
// TODO PERF, substrings, object creation, etc.
|
||||||
if (pattern.IndexOf("://") >= 0)
|
if (pattern.IndexOf("://", StringComparison.Ordinal) >= 0)
|
||||||
{
|
{
|
||||||
string scheme = null;
|
string scheme;
|
||||||
HostString host;
|
HostString host;
|
||||||
PathString path;
|
PathString path;
|
||||||
QueryString query;
|
QueryString query;
|
||||||
|
|
|
||||||
|
|
@ -62,91 +62,90 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
||||||
condition.OrNext = flags.HasFlag(FlagType.Or);
|
condition.OrNext = flags.HasFlag(FlagType.Or);
|
||||||
condition.Input = pattern;
|
condition.Input = pattern;
|
||||||
|
|
||||||
if (input.ConditionType == ConditionType.Regex)
|
switch (input.ConditionType)
|
||||||
{
|
{
|
||||||
if (flags.HasFlag(FlagType.NoCase))
|
case ConditionType.Regex:
|
||||||
{
|
if (flags.HasFlag(FlagType.NoCase))
|
||||||
condition.Match = new RegexMatch(new Regex(input.Operand, RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout), input.Invert);
|
{
|
||||||
}
|
condition.Match = new RegexMatch(new Regex(input.Operand, RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout), input.Invert);
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
condition.Match = new RegexMatch(new Regex(input.Operand, RegexOptions.Compiled, RegexTimeout), input.Invert);
|
{
|
||||||
}
|
condition.Match = new RegexMatch(new Regex(input.Operand, RegexOptions.CultureInvariant | RegexOptions.Compiled, RegexTimeout), input.Invert);
|
||||||
}
|
}
|
||||||
else if (input.ConditionType == ConditionType.IntComp)
|
break;
|
||||||
{
|
case ConditionType.IntComp:
|
||||||
switch (input.OperationType)
|
switch (input.OperationType)
|
||||||
{
|
{
|
||||||
case OperationType.Equal:
|
case OperationType.Equal:
|
||||||
condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.Equal);
|
condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.Equal);
|
||||||
break;
|
break;
|
||||||
case OperationType.Greater:
|
case OperationType.Greater:
|
||||||
condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.Greater);
|
condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.Greater);
|
||||||
break;
|
break;
|
||||||
case OperationType.GreaterEqual:
|
case OperationType.GreaterEqual:
|
||||||
condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.GreaterEqual);
|
condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.GreaterEqual);
|
||||||
break;
|
break;
|
||||||
case OperationType.Less:
|
case OperationType.Less:
|
||||||
condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.Less);
|
condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.Less);
|
||||||
break;
|
break;
|
||||||
case OperationType.LessEqual:
|
case OperationType.LessEqual:
|
||||||
condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.LessEqual);
|
condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.LessEqual);
|
||||||
break;
|
break;
|
||||||
case OperationType.NotEqual:
|
case OperationType.NotEqual:
|
||||||
condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.NotEqual);
|
condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.NotEqual);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentException("Invalid operation for integer comparison.");
|
throw new ArgumentException("Invalid operation for integer comparison.");
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else if (input.ConditionType == ConditionType.StringComp)
|
case ConditionType.StringComp:
|
||||||
{
|
switch (input.OperationType)
|
||||||
switch (input.OperationType)
|
{
|
||||||
{
|
case OperationType.Equal:
|
||||||
case OperationType.Equal:
|
condition.Match = new StringMatch(input.Operand, StringOperationType.Equal, input.Invert);
|
||||||
condition.Match = new StringMatch(input.Operand, StringOperationType.Equal);
|
break;
|
||||||
break;
|
case OperationType.Greater:
|
||||||
case OperationType.Greater:
|
condition.Match = new StringMatch(input.Operand, StringOperationType.Greater, input.Invert);
|
||||||
condition.Match = new StringMatch(input.Operand, StringOperationType.Greater);
|
break;
|
||||||
break;
|
case OperationType.GreaterEqual:
|
||||||
case OperationType.GreaterEqual:
|
condition.Match = new StringMatch(input.Operand, StringOperationType.GreaterEqual, input.Invert);
|
||||||
condition.Match = new StringMatch(input.Operand, StringOperationType.GreaterEqual);
|
break;
|
||||||
break;
|
case OperationType.Less:
|
||||||
case OperationType.Less:
|
condition.Match = new StringMatch(input.Operand, StringOperationType.Less, input.Invert);
|
||||||
condition.Match = new StringMatch(input.Operand, StringOperationType.Less);
|
break;
|
||||||
break;
|
case OperationType.LessEqual:
|
||||||
case OperationType.LessEqual:
|
condition.Match = new StringMatch(input.Operand, StringOperationType.LessEqual, input.Invert);
|
||||||
condition.Match = new StringMatch(input.Operand, StringOperationType.LessEqual);
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
throw new ArgumentException("Invalid operation for string comparison.");
|
||||||
throw new ArgumentException("Invalid operation for string comparison.");
|
}
|
||||||
}
|
break;
|
||||||
}
|
default:
|
||||||
else
|
switch (input.OperationType)
|
||||||
{
|
{
|
||||||
switch (input.OperationType)
|
case OperationType.Directory:
|
||||||
{
|
condition.Match = new IsDirectoryMatch(input.Invert);
|
||||||
case OperationType.Directory:
|
break;
|
||||||
condition.Match = new IsDirectoryMatch(input.Invert);
|
case OperationType.RegularFile:
|
||||||
break;
|
condition.Match = new IsFileMatch(input.Invert);
|
||||||
case OperationType.RegularFile:
|
break;
|
||||||
condition.Match = new IsFileMatch(input.Invert);
|
case OperationType.ExistingFile:
|
||||||
break;
|
condition.Match = new IsFileMatch(input.Invert);
|
||||||
case OperationType.ExistingFile:
|
break;
|
||||||
condition.Match = new IsFileMatch(input.Invert);
|
case OperationType.SymbolicLink:
|
||||||
break;
|
throw new NotImplementedException("Symbolic links are not implemented");
|
||||||
case OperationType.SymbolicLink:
|
case OperationType.Size:
|
||||||
throw new NotImplementedException("Symbolic links are not implemented");
|
condition.Match = new FileSizeMatch(input.Invert);
|
||||||
case OperationType.Size:
|
break;
|
||||||
condition.Match = new FileSizeMatch(input.Invert);
|
case OperationType.ExistingUrl:
|
||||||
break;
|
throw new NotImplementedException("Existing Url lookups not implemented");
|
||||||
case OperationType.ExistingUrl:
|
case OperationType.Executable:
|
||||||
throw new NotImplementedException("Existing Url lookups not implemented");
|
throw new NotImplementedException("Executable Property search is not implemented");
|
||||||
case OperationType.Executable:
|
default:
|
||||||
throw new NotImplementedException("Executable Property search is not implemented");
|
throw new ArgumentException("Invalid operation for property comparison.");
|
||||||
default:
|
}
|
||||||
throw new ArgumentException("Invalid operation for property comparison.");
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_conditions.ConditionList.Add(condition);
|
_conditions.ConditionList.Add(condition);
|
||||||
}
|
}
|
||||||
|
|
@ -157,11 +156,11 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
||||||
{
|
{
|
||||||
if (flags.HasFlag(FlagType.NoCase))
|
if (flags.HasFlag(FlagType.NoCase))
|
||||||
{
|
{
|
||||||
_match = new RegexMatch(new Regex(input.Operand, RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout), input.Invert);
|
_match = new RegexMatch(new Regex(input.Operand, RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout), input.Invert);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_match = new RegexMatch(new Regex(input.Operand, RegexOptions.Compiled, RegexTimeout), input.Invert);
|
_match = new RegexMatch(new Regex(input.Operand, RegexOptions.CultureInvariant | RegexOptions.Compiled, RegexTimeout), input.Invert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
||||||
{
|
{
|
||||||
public ParsedModRewriteInput ParseRuleRegex(string regex)
|
public ParsedModRewriteInput ParseRuleRegex(string regex)
|
||||||
{
|
{
|
||||||
if (regex == null || regex == string.Empty)
|
if (string.IsNullOrEmpty(regex))
|
||||||
{
|
{
|
||||||
throw new FormatException("Regex expression is null");
|
throw new FormatException("Regex expression is null");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
||||||
{
|
{
|
||||||
private const char Percent = '%';
|
private const char Percent = '%';
|
||||||
private const char Dollar = '$';
|
private const char Dollar = '$';
|
||||||
private const char Space = ' ';
|
|
||||||
private const char Colon = ':';
|
private const char Colon = ':';
|
||||||
private const char OpenBrace = '{';
|
private const char OpenBrace = '{';
|
||||||
private const char CloseBrace = '}';
|
private const char CloseBrace = '}';
|
||||||
|
|
@ -41,43 +40,41 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
||||||
var results = new List<PatternSegment>();
|
var results = new List<PatternSegment>();
|
||||||
while (context.Next())
|
while (context.Next())
|
||||||
{
|
{
|
||||||
if (context.Current == Percent)
|
switch (context.Current)
|
||||||
{
|
{
|
||||||
// This is a server parameter, parse for a condition variable
|
case Percent:
|
||||||
if (!context.Next())
|
// This is a server parameter, parse for a condition variable
|
||||||
{
|
if (!context.Next())
|
||||||
throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(testString, context.Index));
|
{
|
||||||
}
|
throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(testString, context.Index));
|
||||||
ParseConditionParameter(context, results);
|
}
|
||||||
}
|
ParseConditionParameter(context, results);
|
||||||
else if (context.Current == Dollar)
|
break;
|
||||||
{
|
case Dollar:
|
||||||
// This is a parameter from the rule, verify that it is a number from 0 to 9 directly after it
|
// This is a parameter from the rule, verify that it is a number from 0 to 9 directly after it
|
||||||
// and create a new Pattern Segment.
|
// and create a new Pattern Segment.
|
||||||
if (!context.Next())
|
if (!context.Next())
|
||||||
{
|
{
|
||||||
throw new FormatException(Resources.FormatError_InputParserNoBackreference(context.Index));
|
throw new FormatException(Resources.FormatError_InputParserNoBackreference(context.Index));
|
||||||
}
|
}
|
||||||
context.Mark();
|
context.Mark();
|
||||||
if (context.Current >= '0' && context.Current <= '9')
|
if (context.Current >= '0' && context.Current <= '9')
|
||||||
{
|
{
|
||||||
context.Next();
|
context.Next();
|
||||||
var ruleVariable = context.Capture();
|
var ruleVariable = context.Capture();
|
||||||
context.Back();
|
context.Back();
|
||||||
var parsedIndex = int.Parse(ruleVariable);
|
var parsedIndex = int.Parse(ruleVariable);
|
||||||
|
|
||||||
results.Add(new RuleMatchSegment(parsedIndex));
|
results.Add(new RuleMatchSegment(parsedIndex));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new FormatException(Resources.FormatError_InputParserInvalidInteger(testString, context.Index));
|
throw new FormatException(Resources.FormatError_InputParserInvalidInteger(testString, context.Index));
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else
|
default:
|
||||||
{
|
ParseLiteral(context, results);
|
||||||
// Parse for literals, which will return on either the end of the test string
|
break;
|
||||||
// or when it hits a special character
|
|
||||||
ParseLiteral(context, results);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Pattern(results);
|
return new Pattern(results);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
||||||
private const char Space = ' ';
|
private const char Space = ' ';
|
||||||
private const char Escape = '\\';
|
private const char Escape = '\\';
|
||||||
private const char Tab = '\t';
|
private const char Tab = '\t';
|
||||||
|
private const char Quote = '"';
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Splits a string on whitespace, ignoring spaces, creating into a list of strings.
|
/// Splits a string on whitespace, ignoring spaces, creating into a list of strings.
|
||||||
|
|
@ -36,49 +37,51 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
||||||
context.Mark();
|
context.Mark();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (context.Current == Escape)
|
switch (context.Current)
|
||||||
{
|
{
|
||||||
// Need to progress such that the next character is not evaluated.
|
case Escape:
|
||||||
if (!context.Next())
|
// Need to progress such that the next character is not evaluated.
|
||||||
{
|
if (!context.Next())
|
||||||
// Means that a character was not escaped appropriately Ex: "foo\"
|
{
|
||||||
throw new FormatException($"Invalid escaper character in string: {rule}");
|
// Means that a character was not escaped appropriately Ex: "foo\"
|
||||||
}
|
throw new FormatException($"Invalid escaper character in string: {rule}");
|
||||||
}
|
}
|
||||||
else if (context.Current == '"')
|
break;
|
||||||
{
|
case Quote:
|
||||||
// Ignore all characters until the next quote is hit
|
// Ignore all characters until the next quote is hit
|
||||||
if (!context.Next())
|
|
||||||
{
|
|
||||||
throw new FormatException($"Mismatched number of quotes: {rule}");
|
|
||||||
}
|
|
||||||
while (context.Current != '"')
|
|
||||||
{
|
|
||||||
if (!context.Next())
|
if (!context.Next())
|
||||||
{
|
{
|
||||||
throw new FormatException($"Mismatched number of quotes: {rule}");
|
throw new FormatException($"Mismatched number of quotes: {rule}");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
while (context.Current != Quote)
|
||||||
else if (context.Current == Space || context.Current == Tab)
|
|
||||||
{
|
|
||||||
// time to capture!
|
|
||||||
var token = context.Capture();
|
|
||||||
if (!string.IsNullOrEmpty(token))
|
|
||||||
{
|
|
||||||
tokens.Add(token);
|
|
||||||
while (context.Current == Space || context.Current == Tab)
|
|
||||||
{
|
{
|
||||||
if (!context.Next())
|
if (!context.Next())
|
||||||
{
|
{
|
||||||
// At end of string, we can return at this point.
|
throw new FormatException($"Mismatched number of quotes: {rule}");
|
||||||
RemoveQuotesAndEscapeCharacters(tokens);
|
|
||||||
return tokens;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.Mark();
|
break;
|
||||||
context.Back();
|
case Space:
|
||||||
}
|
case Tab:
|
||||||
|
// time to capture!
|
||||||
|
var token = context.Capture();
|
||||||
|
if (!string.IsNullOrEmpty(token))
|
||||||
|
{
|
||||||
|
tokens.Add(token);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!context.Next())
|
||||||
|
{
|
||||||
|
// At end of string, we can return at this point.
|
||||||
|
RemoveQuotesAndEscapeCharacters(tokens);
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
} while (context.Current == Space || context.Current == Tab);
|
||||||
|
context.Mark();
|
||||||
|
context.Back();
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (!context.Next())
|
if (!context.Next())
|
||||||
{
|
{
|
||||||
|
|
@ -99,9 +102,9 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
||||||
// Need to remove leading and trailing slashes if they exist.
|
// Need to remove leading and trailing slashes if they exist.
|
||||||
// This is on start-up, so more forgivening towards substrings/ new strings
|
// This is on start-up, so more forgivening towards substrings/ new strings
|
||||||
// If this is a perf/memory problem, discuss later.
|
// If this is a perf/memory problem, discuss later.
|
||||||
private void RemoveQuotesAndEscapeCharacters(List<string> tokens)
|
private static void RemoveQuotesAndEscapeCharacters(IList<string> tokens)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < tokens.Count; i++)
|
for (var i = 0; i < tokens.Count; i++)
|
||||||
{
|
{
|
||||||
var token = tokens[i];
|
var token = tokens[i];
|
||||||
var trimmed = token.Trim('\"');
|
var trimmed = token.Trim('\"');
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||||
Index = -1;
|
Index = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public char Current
|
public char Current => (Index < Template.Length && Index >= 0) ? Template[Index] : (char)0;
|
||||||
{
|
|
||||||
get { return (Index < Template.Length && Index >= 0) ? Template[Index] : (char)0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Back()
|
public bool Back()
|
||||||
{
|
{
|
||||||
|
|
@ -62,10 +59,5 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Error()
|
|
||||||
{
|
|
||||||
return string.Format("Syntax Error at index: ", Index, " with character: ", Current);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||||
public class Pattern
|
public class Pattern
|
||||||
{
|
{
|
||||||
public IList<PatternSegment> PatternSegments { get; }
|
public IList<PatternSegment> PatternSegments { get; }
|
||||||
public Pattern(List<PatternSegment> patternSegments)
|
public Pattern(IList<PatternSegment> patternSegments)
|
||||||
{
|
{
|
||||||
PatternSegments = patternSegments;
|
PatternSegments = patternSegments;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,16 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
||||||
{
|
{
|
||||||
public class ConditionMatchSegment : PatternSegment
|
public class ConditionMatchSegment : PatternSegment
|
||||||
{
|
{
|
||||||
public int Index { get; set; }
|
private readonly int _index;
|
||||||
|
|
||||||
public ConditionMatchSegment(int index)
|
public ConditionMatchSegment(int index)
|
||||||
{
|
{
|
||||||
Index = index;
|
_index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||||
{
|
{
|
||||||
return condMatch?.BackReference[Index]?.Value;
|
return condMatch?.BackReference[_index].Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
||||||
{
|
{
|
||||||
public class DateTimeSegment : PatternSegment
|
public class DateTimeSegment : PatternSegment
|
||||||
{
|
{
|
||||||
private DateTimePortion _portion;
|
private readonly DateTimePortion _portion;
|
||||||
|
|
||||||
public DateTimeSegment(string segment)
|
public DateTimeSegment(string segment)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,16 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
||||||
{
|
{
|
||||||
public class HeaderSegment : PatternSegment
|
public class HeaderSegment : PatternSegment
|
||||||
{
|
{
|
||||||
public string Header { get; set; }
|
private readonly string _header;
|
||||||
|
|
||||||
public HeaderSegment(string header)
|
public HeaderSegment(string header)
|
||||||
{
|
{
|
||||||
Header = header;
|
_header = header;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||||
{
|
{
|
||||||
return context.HttpContext.Request.Headers[Header];
|
return context.HttpContext.Request.Headers[_header];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,16 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
||||||
{
|
{
|
||||||
public class LiteralSegment : PatternSegment
|
public class LiteralSegment : PatternSegment
|
||||||
{
|
{
|
||||||
public string Literal { get; set; }
|
private readonly string _literal;
|
||||||
|
|
||||||
public LiteralSegment(string literal)
|
public LiteralSegment(string literal)
|
||||||
{
|
{
|
||||||
Literal = literal;
|
_literal = literal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||||
{
|
{
|
||||||
return Literal;
|
return _literal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,16 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
||||||
{
|
{
|
||||||
public class RuleMatchSegment : PatternSegment
|
public class RuleMatchSegment : PatternSegment
|
||||||
{
|
{
|
||||||
public int Index { get; set; }
|
private readonly int _index;
|
||||||
|
|
||||||
public RuleMatchSegment(int index)
|
public RuleMatchSegment(int index)
|
||||||
{
|
{
|
||||||
Index = index;
|
_index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||||
{
|
{
|
||||||
return ruleMatch?.BackReference[Index]?.Value;
|
return ruleMatch?.BackReference[_index].Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
||||||
{
|
{
|
||||||
public class ToLowerSegment : PatternSegment
|
public class ToLowerSegment : PatternSegment
|
||||||
{
|
{
|
||||||
public Pattern Pattern { get; set; }
|
private readonly Pattern _pattern;
|
||||||
|
|
||||||
public ToLowerSegment(Pattern pattern)
|
public ToLowerSegment(Pattern pattern)
|
||||||
{
|
{
|
||||||
Pattern = pattern;
|
_pattern = pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
||||||
// lowercase segments.
|
// lowercase segments.
|
||||||
var tempBuilder = context.Builder;
|
var tempBuilder = context.Builder;
|
||||||
context.Builder = new StringBuilder(64);
|
context.Builder = new StringBuilder(64);
|
||||||
var pattern = Pattern.Evaluate(context, ruleMatch, condMatch);
|
var pattern = _pattern.Evaluate(context, ruleMatch, condMatch);
|
||||||
context.Builder = tempBuilder;
|
context.Builder = tempBuilder;
|
||||||
return pattern.ToLowerInvariant();
|
return pattern.ToLowerInvariant();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,18 +8,18 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
||||||
{
|
{
|
||||||
public class UrlEncodeSegment : PatternSegment
|
public class UrlEncodeSegment : PatternSegment
|
||||||
{
|
{
|
||||||
public Pattern Pattern { get; set; }
|
private readonly Pattern _pattern;
|
||||||
|
|
||||||
public UrlEncodeSegment(Pattern pattern)
|
public UrlEncodeSegment(Pattern pattern)
|
||||||
{
|
{
|
||||||
Pattern = pattern;
|
_pattern = pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||||
{
|
{
|
||||||
var tempBuilder = context.Builder;
|
var tempBuilder = context.Builder;
|
||||||
context.Builder = new StringBuilder(64);
|
context.Builder = new StringBuilder(64);
|
||||||
var pattern = Pattern.Evaluate(context, ruleMatch, condMatch);
|
var pattern = _pattern.Evaluate(context, ruleMatch, condMatch);
|
||||||
context.Builder = tempBuilder;
|
context.Builder = tempBuilder;
|
||||||
return UrlEncoder.Default.Encode(pattern);
|
return UrlEncoder.Default.Encode(pattern);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Rewrite.Internal
|
namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Extensions;
|
using Microsoft.AspNetCore.Http.Extensions;
|
||||||
|
|
||||||
|
|
@ -30,7 +31,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
|
||||||
// TODO PERF, substrings, object creation, etc.
|
// TODO PERF, substrings, object creation, etc.
|
||||||
if (pattern.IndexOf("://") >= 0)
|
if (pattern.IndexOf("://") >= 0)
|
||||||
{
|
{
|
||||||
string scheme = null;
|
string scheme;
|
||||||
HostString host;
|
HostString host;
|
||||||
PathString path;
|
PathString path;
|
||||||
QueryString query;
|
QueryString query;
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,16 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
|
||||||
{
|
{
|
||||||
public class VoidAction : UrlAction
|
public class VoidAction : UrlAction
|
||||||
{
|
{
|
||||||
|
private readonly RuleResult _results;
|
||||||
|
|
||||||
|
public VoidAction(RuleResult results)
|
||||||
|
{
|
||||||
|
_results = results;
|
||||||
|
}
|
||||||
// Explicitly say that nothing happens
|
// Explicitly say that nothing happens
|
||||||
public override RuleResult ApplyAction(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
public override RuleResult ApplyAction(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||||
{
|
{
|
||||||
return RuleResult.Continue;
|
return _results;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||||
{
|
{
|
||||||
public abstract class UrlMatch
|
public abstract class UrlMatch
|
||||||
{
|
{
|
||||||
public bool Negate { get; set; }
|
protected bool Negate { get; set; }
|
||||||
public abstract MatchResults Evaluate(string input, RewriteContext context);
|
public abstract MatchResults Evaluate(string input, RewriteContext context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,19 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
|
||||||
{
|
{
|
||||||
public class ExactMatch : UrlMatch
|
public class ExactMatch : UrlMatch
|
||||||
{
|
{
|
||||||
public bool IgnoreCase { get; }
|
private readonly bool _ignoreCase;
|
||||||
public string StringMatch { get; }
|
private readonly string _stringMatch;
|
||||||
|
|
||||||
public ExactMatch(bool ignoreCase, string input, bool negate)
|
public ExactMatch(bool ignoreCase, string input, bool negate)
|
||||||
{
|
{
|
||||||
IgnoreCase = ignoreCase;
|
_ignoreCase = ignoreCase;
|
||||||
StringMatch = input;
|
_stringMatch = input;
|
||||||
Negate = negate;
|
Negate = negate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override MatchResults Evaluate(string pattern, RewriteContext context)
|
public override MatchResults Evaluate(string pattern, RewriteContext context)
|
||||||
{
|
{
|
||||||
var pathMatch = string.Compare(pattern, StringMatch, IgnoreCase);
|
var pathMatch = string.Compare(pattern, _stringMatch, _ignoreCase);
|
||||||
return new MatchResults { Success = ((pathMatch == 0) != Negate) };
|
return new MatchResults { Success = ((pathMatch == 0) != Negate) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,12 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
|
||||||
{
|
{
|
||||||
public class IntegerMatch : UrlMatch
|
public class IntegerMatch : UrlMatch
|
||||||
{
|
{
|
||||||
public int Value { get; }
|
private readonly int _value;
|
||||||
public IntegerOperationType Operation { get; }
|
private readonly IntegerOperationType _operation;
|
||||||
public IntegerMatch(int value, IntegerOperationType operation)
|
public IntegerMatch(int value, IntegerOperationType operation)
|
||||||
{
|
{
|
||||||
Value = value;
|
_value = value;
|
||||||
Operation = operation;
|
_operation = operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntegerMatch(string value, IntegerOperationType operation)
|
public IntegerMatch(string value, IntegerOperationType operation)
|
||||||
|
|
@ -23,8 +23,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
|
||||||
{
|
{
|
||||||
throw new FormatException("Syntax error for integers in comparison.");
|
throw new FormatException("Syntax error for integers in comparison.");
|
||||||
}
|
}
|
||||||
Value = compValue;
|
_value = compValue;
|
||||||
Operation = operation;
|
_operation = operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override MatchResults Evaluate(string input, RewriteContext context)
|
public override MatchResults Evaluate(string input, RewriteContext context)
|
||||||
|
|
@ -35,20 +35,20 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
|
||||||
return MatchResults.EmptyFailure;
|
return MatchResults.EmptyFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Operation)
|
switch (_operation)
|
||||||
{
|
{
|
||||||
case IntegerOperationType.Equal:
|
case IntegerOperationType.Equal:
|
||||||
return compValue == Value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
return compValue == _value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
||||||
case IntegerOperationType.Greater:
|
case IntegerOperationType.Greater:
|
||||||
return compValue > Value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
return compValue > _value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
||||||
case IntegerOperationType.GreaterEqual:
|
case IntegerOperationType.GreaterEqual:
|
||||||
return compValue >= Value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
return compValue >= _value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
||||||
case IntegerOperationType.Less:
|
case IntegerOperationType.Less:
|
||||||
return compValue < Value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
return compValue < _value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
||||||
case IntegerOperationType.LessEqual:
|
case IntegerOperationType.LessEqual:
|
||||||
return compValue <= Value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
return compValue <= _value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
||||||
case IntegerOperationType.NotEqual:
|
case IntegerOperationType.NotEqual:
|
||||||
return compValue != Value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
return compValue != _value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
|
||||||
{
|
{
|
||||||
public class IsDirectoryMatch : UrlMatch
|
public class IsDirectoryMatch : UrlMatch
|
||||||
{
|
{
|
||||||
public IsDirectoryMatch( bool negate)
|
public IsDirectoryMatch(bool negate)
|
||||||
{
|
{
|
||||||
Negate = negate;
|
Negate = negate;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,23 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
|
namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
|
||||||
{
|
{
|
||||||
public class RegexMatch : UrlMatch
|
public class RegexMatch : UrlMatch
|
||||||
{
|
{
|
||||||
private static readonly TimeSpan RegexTimeout = TimeSpan.FromMilliseconds(1);
|
private readonly Regex _match;
|
||||||
|
|
||||||
public Regex Match { get; }
|
|
||||||
|
|
||||||
public RegexMatch(Regex match, bool negate)
|
public RegexMatch(Regex match, bool negate)
|
||||||
{
|
{
|
||||||
Match = match;
|
_match = match;
|
||||||
Negate = negate;
|
Negate = negate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override MatchResults Evaluate(string pattern, RewriteContext context)
|
public override MatchResults Evaluate(string pattern, RewriteContext context)
|
||||||
{
|
{
|
||||||
var res = Match.Match(pattern);
|
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)};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,29 +5,31 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
|
||||||
{
|
{
|
||||||
public class StringMatch : UrlMatch
|
public class StringMatch : UrlMatch
|
||||||
{
|
{
|
||||||
public string Value { get; set; }
|
private readonly string _value;
|
||||||
public StringOperationType Operation { get; set; }
|
private readonly StringOperationType _operation;
|
||||||
public bool IgnoreCase { get; set; }
|
private readonly bool _ignoreCase;
|
||||||
public StringMatch(string value, StringOperationType operation)
|
|
||||||
|
public StringMatch(string value, StringOperationType operation, bool ignoreCase)
|
||||||
{
|
{
|
||||||
Value = value;
|
_value = value;
|
||||||
Operation = operation;
|
_operation = operation;
|
||||||
|
_ignoreCase = ignoreCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override MatchResults Evaluate(string input, RewriteContext context)
|
public override MatchResults Evaluate(string input, RewriteContext context)
|
||||||
{
|
{
|
||||||
switch (Operation)
|
switch (_operation)
|
||||||
{
|
{
|
||||||
case StringOperationType.Equal:
|
case StringOperationType.Equal:
|
||||||
return string.Compare(input, Value, IgnoreCase) == 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
return string.Compare(input, _value, _ignoreCase) == 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
||||||
case StringOperationType.Greater:
|
case StringOperationType.Greater:
|
||||||
return string.Compare(input, Value, IgnoreCase) > 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
return string.Compare(input, _value, _ignoreCase) > 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
||||||
case StringOperationType.GreaterEqual:
|
case StringOperationType.GreaterEqual:
|
||||||
return string.Compare(input, Value, IgnoreCase) >= 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
return string.Compare(input, _value, _ignoreCase) >= 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
||||||
case StringOperationType.Less:
|
case StringOperationType.Less:
|
||||||
return string.Compare(input, Value, IgnoreCase) < 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
return string.Compare(input, _value, _ignoreCase) < 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
||||||
case StringOperationType.LessEqual:
|
case StringOperationType.LessEqual:
|
||||||
return string.Compare(input, Value, IgnoreCase) <= 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
return string.Compare(input, _value, _ignoreCase) <= 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
||||||
{
|
{
|
||||||
public class FileParser
|
public class FileParser
|
||||||
{
|
{
|
||||||
private static readonly TimeSpan RegexTimeout = TimeSpan.FromMilliseconds(1);
|
private readonly InputParser _inputParser = new InputParser();
|
||||||
|
|
||||||
private InputParser _inputParser = new InputParser();
|
|
||||||
|
|
||||||
public List<UrlRewriteRule> Parse(TextReader reader)
|
public List<UrlRewriteRule> Parse(TextReader reader)
|
||||||
{
|
{
|
||||||
|
|
@ -168,12 +166,10 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
||||||
|
|
||||||
var parsedPatternString = condition.Attribute(RewriteTags.Pattern)?.Value;
|
var parsedPatternString = condition.Attribute(RewriteTags.Pattern)?.Value;
|
||||||
|
|
||||||
Pattern input = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
input = _inputParser.ParseInputString(parsedInputString);
|
var input = _inputParser.ParseInputString(parsedInputString);
|
||||||
builder.AddUrlCondition(input, parsedPatternString, patternSyntax, matchType, ignoreCase, negate);
|
builder.AddUrlCondition(input, parsedPatternString, patternSyntax, matchType, ignoreCase, negate);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (FormatException formatException)
|
catch (FormatException formatException)
|
||||||
{
|
{
|
||||||
|
|
@ -212,14 +208,14 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThrowUrlFormatException(XElement element, string message)
|
private static void ThrowUrlFormatException(XElement element, string message)
|
||||||
{
|
{
|
||||||
var line = ((IXmlLineInfo)element).LineNumber;
|
var line = ((IXmlLineInfo)element).LineNumber;
|
||||||
var col = ((IXmlLineInfo)element).LinePosition;
|
var col = ((IXmlLineInfo)element).LinePosition;
|
||||||
throw new FormatException(Resources.FormatError_UrlRewriteParseError(message, line, col));
|
throw new FormatException(Resources.FormatError_UrlRewriteParseError(message, line, col));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThrowUrlFormatException(XElement element, string message, Exception ex)
|
private static void ThrowUrlFormatException(XElement element, string message, Exception ex)
|
||||||
{
|
{
|
||||||
var line = ((IXmlLineInfo)element).LineNumber;
|
var line = ((IXmlLineInfo)element).LineNumber;
|
||||||
var col = ((IXmlLineInfo)element).LinePosition;
|
var col = ((IXmlLineInfo)element).LinePosition;
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ParseLiteral(ParserContext context, List<PatternSegment> results)
|
private static void ParseLiteral(ParserContext context, List<PatternSegment> results)
|
||||||
{
|
{
|
||||||
context.Mark();
|
context.Mark();
|
||||||
string literal;
|
string literal;
|
||||||
|
|
@ -186,7 +186,6 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
||||||
}
|
}
|
||||||
|
|
||||||
results.Add(new LiteralSegment(literal));
|
results.Add(new LiteralSegment(literal));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
||||||
switch (actionType)
|
switch (actionType)
|
||||||
{
|
{
|
||||||
case ActionType.None:
|
case ActionType.None:
|
||||||
_action = new VoidAction();
|
_action = new VoidAction(stopProcessing ? RuleResult.StopRules : RuleResult.Continue);
|
||||||
break;
|
break;
|
||||||
case ActionType.Rewrite:
|
case ActionType.Rewrite:
|
||||||
if (appendQueryString)
|
if (appendQueryString)
|
||||||
|
|
@ -79,12 +79,12 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
||||||
{
|
{
|
||||||
if (ignoreCase)
|
if (ignoreCase)
|
||||||
{
|
{
|
||||||
var regex = new Regex(input, RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout);
|
var regex = new Regex(input, RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout);
|
||||||
_initialMatch = new RegexMatch(regex, negate);
|
_initialMatch = new RegexMatch(regex, negate);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var regex = new Regex(input, RegexOptions.Compiled, RegexTimeout);
|
var regex = new Regex(input, RegexOptions.CultureInvariant | RegexOptions.Compiled, RegexTimeout);
|
||||||
_initialMatch = new RegexMatch(regex, negate);
|
_initialMatch = new RegexMatch(regex, negate);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -121,11 +121,11 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
||||||
Regex regex = null;
|
Regex regex = null;
|
||||||
if (ignoreCase)
|
if (ignoreCase)
|
||||||
{
|
{
|
||||||
regex = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout);
|
regex = new Regex(pattern, RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
regex = new Regex(pattern, RegexOptions.Compiled, RegexTimeout);
|
regex = new Regex(pattern, RegexOptions.CultureInvariant | RegexOptions.Compiled, RegexTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
_conditions.ConditionList.Add(new Condition { Input = input, Match = new RegexMatch(regex, negate), OrNext = _matchAny});
|
_conditions.ConditionList.Add(new Condition { Input = input, Match = new RegexMatch(regex, negate), OrNext = _matchAny});
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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 System.Diagnostics;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Rewrite.Internal
|
namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||||
{
|
{
|
||||||
|
|
@ -26,9 +23,18 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||||
// Due to the path string always having a leading slash,
|
// Due to the path string always having a leading slash,
|
||||||
// remove it from the path before regex comparison
|
// remove it from the path before regex comparison
|
||||||
// TODO may need to check if there is a leading slash and remove conditionally
|
// TODO may need to check if there is a leading slash and remove conditionally
|
||||||
var initMatchRes = InitialMatch.Evaluate(context.HttpContext.Request.Path.ToString().Substring(1), context);
|
var path = context.HttpContext.Request.Path;
|
||||||
|
MatchResults initMatchResults;
|
||||||
|
if (path == PathString.Empty)
|
||||||
|
{
|
||||||
|
initMatchResults = InitialMatch.Evaluate(path.ToString(), context);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
initMatchResults = InitialMatch.Evaluate(path.ToString().Substring(1), context);
|
||||||
|
}
|
||||||
|
|
||||||
if (!initMatchRes.Success)
|
if (!initMatchResults.Success)
|
||||||
{
|
{
|
||||||
return RuleResult.Continue;
|
return RuleResult.Continue;
|
||||||
}
|
}
|
||||||
|
|
@ -36,7 +42,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||||
MatchResults condMatchRes = null;
|
MatchResults condMatchRes = null;
|
||||||
if (Conditions != null)
|
if (Conditions != null)
|
||||||
{
|
{
|
||||||
condMatchRes = Conditions.Evaluate(context, initMatchRes);
|
condMatchRes = Conditions.Evaluate(context, initMatchResults);
|
||||||
if (!condMatchRes.Success)
|
if (!condMatchRes.Success)
|
||||||
{
|
{
|
||||||
return RuleResult.Continue;
|
return RuleResult.Continue;
|
||||||
|
|
@ -44,7 +50,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
// at this point we know the rule passed, evaluate the replacement.
|
// at this point we know the rule passed, evaluate the replacement.
|
||||||
return Action.ApplyAction(context, initMatchRes, condMatchRes);
|
return Action.ApplyAction(context, initMatchResults, condMatchRes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -69,6 +69,8 @@ namespace Microsoft.AspNetCore.Rewrite
|
||||||
return CompletedTask;
|
return CompletedTask;
|
||||||
case RuleTerminiation.StopRules:
|
case RuleTerminiation.StopRules:
|
||||||
return _next(context);
|
return _next(context);
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException($"Invalid rule termination {result}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _next(context);
|
return _next(context);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
// TODO add more of these
|
||||||
|
public class UrlRewriteApplicationTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void ApplyRule_AssertStopProcessingFlagWillTerminateOnNoAction()
|
||||||
|
{
|
||||||
|
var xml = new StringReader(@"<rewrite>
|
||||||
|
<rules>
|
||||||
|
<rule name=""Test"" stopProcessing=""true"">
|
||||||
|
<match url = ""(.*)""/>
|
||||||
|
<action type = ""None""/>
|
||||||
|
</rule>
|
||||||
|
</rules>
|
||||||
|
</rewrite>");
|
||||||
|
var rules = new FileParser().Parse(xml);
|
||||||
|
|
||||||
|
Assert.Equal(rules.Count, 1);
|
||||||
|
var ruleResults = rules.FirstOrDefault().ApplyRule(new RewriteContext {HttpContext = new DefaultHttpContext()});
|
||||||
|
Assert.Equal(ruleResults.Result, RuleTerminiation.StopRules);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ApplyRule_AssertNoTerminateFlagWillNotTerminateOnNoAction()
|
||||||
|
{
|
||||||
|
var xml = new StringReader(@"<rewrite>
|
||||||
|
<rules>
|
||||||
|
<rule name=""Test"">
|
||||||
|
<match url = ""(.*)"" ignoreCase=""false"" />
|
||||||
|
<action type = ""None""/>
|
||||||
|
</rule>
|
||||||
|
</rules>
|
||||||
|
</rewrite>");
|
||||||
|
var rules = new FileParser().Parse(xml);
|
||||||
|
|
||||||
|
Assert.Equal(rules.Count, 1);
|
||||||
|
var ruleResults = rules.FirstOrDefault().ApplyRule(new RewriteContext { HttpContext = new DefaultHttpContext() });
|
||||||
|
Assert.Equal(ruleResults.Result, RuleTerminiation.Continue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue