Make condition collection a first class citizen (#198)
This commit is contained in:
parent
b254f42d19
commit
ae7d0b9582
|
|
@ -22,7 +22,6 @@ namespace RewriteSample
|
|||
.AddApacheModRewrite(env.ContentRootFileProvider, "Rewrite.txt");
|
||||
|
||||
app.UseRewriter(options);
|
||||
|
||||
app.Run(context => context.Response.WriteAsync($"Rewritten Url: {context.Request.Path + context.Request.QueryString}"));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite
|
|||
BackReferenceCollection condBackReferences = null;
|
||||
if (Conditions != null)
|
||||
{
|
||||
var condResult = ConditionHelper.Evaluate(Conditions, context, initMatchRes.BackReferences);
|
||||
var condResult = ConditionEvaluator.Evaluate(Conditions, context, initMatchRes.BackReferences);
|
||||
if (!condResult.Success)
|
||||
{
|
||||
context.Logger?.ModRewriteDidNotMatchRule();
|
||||
|
|
@ -51,4 +51,4 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite
|
||||
{
|
||||
public class Condition
|
||||
{
|
||||
|
|
@ -15,4 +15,4 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
|||
return Match.Evaluate(pattern, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite
|
||||
{
|
||||
public static class ConditionHelper
|
||||
public static class ConditionEvaluator
|
||||
{
|
||||
public static MatchResults Evaluate(IEnumerable<Condition> conditions, RewriteContext context, BackReferenceCollection backReferences)
|
||||
{
|
||||
|
|
@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
|||
return condResult;
|
||||
}
|
||||
|
||||
if (condResult.Success && trackAllCaptures && prevBackReferences!= null)
|
||||
if (condResult.Success && trackAllCaptures && prevBackReferences != null)
|
||||
{
|
||||
prevBackReferences.Add(currentBackReferences);
|
||||
currentBackReferences = prevBackReferences;
|
||||
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
|||
prevBackReferences = currentBackReferences;
|
||||
}
|
||||
|
||||
return new MatchResults { BackReferences = prevBackReferences, Success = condResult.Success }; ;
|
||||
return new MatchResults { BackReferences = prevBackReferences, Success = condResult.Success };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -222,4 +222,4 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// 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.IISUrlRewrite
|
||||
{
|
||||
public class Condition
|
||||
{
|
||||
public Pattern Input { get; set; }
|
||||
public UrlMatch Match { get; set; }
|
||||
|
||||
public MatchResults Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)
|
||||
{
|
||||
var pattern = Input.Evaluate(context, ruleBackReferences, conditionBackReferences);
|
||||
return Match.Evaluate(pattern, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// 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;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
||||
{
|
||||
public class ConditionCollection : IEnumerable<Condition>
|
||||
{
|
||||
private readonly List<Condition> _conditions = new List<Condition>();
|
||||
|
||||
public LogicalGrouping Grouping { get; }
|
||||
public bool TrackAllCaptures { get; }
|
||||
|
||||
public ConditionCollection()
|
||||
:this(LogicalGrouping.MatchAll, trackAllCaptures: false)
|
||||
{
|
||||
}
|
||||
|
||||
public ConditionCollection(LogicalGrouping grouping, bool trackAllCaptures)
|
||||
{
|
||||
Grouping = grouping;
|
||||
TrackAllCaptures = trackAllCaptures;
|
||||
}
|
||||
|
||||
public int Count => _conditions.Count;
|
||||
|
||||
public Condition this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < _conditions.Count)
|
||||
{
|
||||
return _conditions[index];
|
||||
}
|
||||
throw new IndexOutOfRangeException($"Cannot access condition at index {index}. Only {_conditions.Count} conditions were captured.");
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(Condition condition)
|
||||
{
|
||||
if (condition != null)
|
||||
{
|
||||
_conditions.Add(condition);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddConditions(IEnumerable<Condition> conditions)
|
||||
{
|
||||
if (conditions != null)
|
||||
{
|
||||
_conditions.AddRange(conditions);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return _conditions.GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<Condition> GetEnumerator()
|
||||
{
|
||||
return _conditions.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
// 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.IISUrlRewrite
|
||||
{
|
||||
public static class ConditionEvaluator
|
||||
{
|
||||
public static MatchResults Evaluate(ConditionCollection conditions, RewriteContext context, BackReferenceCollection backReferences)
|
||||
{
|
||||
BackReferenceCollection prevBackReferences = null;
|
||||
MatchResults condResult = null;
|
||||
var orSucceeded = false;
|
||||
foreach (var condition in conditions)
|
||||
{
|
||||
if (orSucceeded && conditions.Grouping == LogicalGrouping.MatchAny)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (orSucceeded)
|
||||
{
|
||||
orSucceeded = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
condResult = condition.Evaluate(context, backReferences, prevBackReferences);
|
||||
var currentBackReferences = condResult.BackReferences;
|
||||
if (conditions.Grouping == LogicalGrouping.MatchAny)
|
||||
{
|
||||
orSucceeded = condResult.Success;
|
||||
}
|
||||
else if (!condResult.Success)
|
||||
{
|
||||
return condResult;
|
||||
}
|
||||
|
||||
if (condResult.Success && conditions.TrackAllCaptures && prevBackReferences!= null)
|
||||
{
|
||||
prevBackReferences.Add(currentBackReferences);
|
||||
currentBackReferences = prevBackReferences;
|
||||
}
|
||||
|
||||
prevBackReferences = currentBackReferences;
|
||||
}
|
||||
|
||||
return new MatchResults { BackReferences = prevBackReferences, Success = condResult.Success };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
// 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;
|
||||
|
||||
|
|
@ -11,32 +10,28 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
{
|
||||
public string Name { get; }
|
||||
public UrlMatch InitialMatch { get; }
|
||||
public IList<Condition> Conditions { get; }
|
||||
public ConditionCollection Conditions { get; }
|
||||
public UrlAction Action { get; }
|
||||
public bool TrackAllCaptures { get; }
|
||||
public bool Global { get; }
|
||||
|
||||
public IISUrlRewriteRule(string name,
|
||||
UrlMatch initialMatch,
|
||||
IList<Condition> conditions,
|
||||
UrlAction action,
|
||||
bool trackAllCaptures)
|
||||
: this(name, initialMatch, conditions, action, trackAllCaptures, false)
|
||||
ConditionCollection conditions,
|
||||
UrlAction action)
|
||||
: this(name, initialMatch, conditions, action, false)
|
||||
{
|
||||
}
|
||||
|
||||
public IISUrlRewriteRule(string name,
|
||||
UrlMatch initialMatch,
|
||||
IList<Condition> conditions,
|
||||
ConditionCollection conditions,
|
||||
UrlAction action,
|
||||
bool trackAllCaptures,
|
||||
bool global)
|
||||
{
|
||||
Name = name;
|
||||
InitialMatch = initialMatch;
|
||||
Conditions = conditions;
|
||||
Action = action;
|
||||
TrackAllCaptures = trackAllCaptures;
|
||||
Global = global;
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +59,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
MatchResults condResult = null;
|
||||
if (Conditions != null)
|
||||
{
|
||||
condResult = ConditionHelper.Evaluate(Conditions, context, initMatchResults.BackReferences, TrackAllCaptures);
|
||||
condResult = ConditionEvaluator.Evaluate(Conditions, context, initMatchResults.BackReferences);
|
||||
if (!condResult.Success)
|
||||
{
|
||||
context.Logger?.UrlRewriteDidNotMatchRule(Name);
|
||||
|
|
|
|||
|
|
@ -28,9 +28,20 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
/// compare to the condition. Can contain server variables, back references, etc.
|
||||
/// </summary>
|
||||
/// <param name="testString"></param>
|
||||
/// <param name="global"></param>
|
||||
/// <returns>A new <see cref="Pattern"/>, containing a list of <see cref="PatternSegment"/></returns>
|
||||
public Pattern ParseInputString(string testString, bool global)
|
||||
public Pattern ParseInputString(string testString)
|
||||
{
|
||||
return ParseInputString(testString, UriMatchPart.Path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a pattern, which is a template to create a new test string to
|
||||
/// compare to the condition. Can contain server variables, back references, etc.
|
||||
/// </summary>
|
||||
/// <param name="testString"></param>
|
||||
/// <param name="uriMatchPart">When testString evaluates to a URL segment, specify which part of the URI to evaluate.</param>
|
||||
/// <returns>A new <see cref="Pattern"/>, containing a list of <see cref="PatternSegment"/></returns>
|
||||
public Pattern ParseInputString(string testString, UriMatchPart uriMatchPart)
|
||||
{
|
||||
if (testString == null)
|
||||
{
|
||||
|
|
@ -38,10 +49,10 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
}
|
||||
|
||||
var context = new ParserContext(testString);
|
||||
return ParseString(context, global);
|
||||
return ParseString(context, uriMatchPart);
|
||||
}
|
||||
|
||||
private Pattern ParseString(ParserContext context, bool global)
|
||||
private Pattern ParseString(ParserContext context, UriMatchPart uriMatchPart)
|
||||
{
|
||||
var results = new List<PatternSegment>();
|
||||
while (context.Next())
|
||||
|
|
@ -54,7 +65,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
// missing {
|
||||
throw new FormatException(Resources.FormatError_InputParserMissingCloseBrace(context.Index));
|
||||
}
|
||||
ParseParameter(context, results, global);
|
||||
ParseParameter(context, results, uriMatchPart);
|
||||
}
|
||||
else if (context.Current == CloseBrace)
|
||||
{
|
||||
|
|
@ -70,7 +81,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
return new Pattern(results);
|
||||
}
|
||||
|
||||
private void ParseParameter(ParserContext context, IList<PatternSegment> results, bool global)
|
||||
private void ParseParameter(ParserContext context, IList<PatternSegment> results, UriMatchPart uriMatchPart)
|
||||
{
|
||||
context.Mark();
|
||||
// Four main cases:
|
||||
|
|
@ -86,7 +97,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
{
|
||||
// This is just a server variable, so we do a lookup and verify the server variable exists.
|
||||
parameter = context.Capture();
|
||||
results.Add(ServerVariables.FindServerVariable(parameter, context, global));
|
||||
results.Add(ServerVariables.FindServerVariable(parameter, context, uriMatchPart));
|
||||
return;
|
||||
}
|
||||
else if (context.Current == Colon)
|
||||
|
|
@ -98,7 +109,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
{
|
||||
case "ToLower":
|
||||
{
|
||||
var pattern = ParseString(context, global);
|
||||
var pattern = ParseString(context, uriMatchPart);
|
||||
results.Add(new ToLowerSegment(pattern));
|
||||
|
||||
// at this point, we expect our context to be on the ending closing brace,
|
||||
|
|
@ -116,7 +127,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
}
|
||||
case "UrlEncode":
|
||||
{
|
||||
var pattern = ParseString(context, global);
|
||||
var pattern = ParseString(context, uriMatchPart);
|
||||
results.Add(new UrlEncodeSegment(pattern));
|
||||
|
||||
if (context.Current != CloseBrace)
|
||||
|
|
@ -141,7 +152,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
var rewriteMap = _rewriteMaps?[parameter];
|
||||
if (rewriteMap != null)
|
||||
{
|
||||
var pattern = ParseString(context, global);
|
||||
var pattern = ParseString(context, uriMatchPart);
|
||||
results.Add(new RewriteMapSegment(rewriteMap, pattern));
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
/// </summary>
|
||||
/// <param name="serverVariable">The server variable</param>
|
||||
/// <param name="context">The parser context which is utilized when an exception is thrown</param>
|
||||
/// <param name="global">Indicates if the rule being parsed is a global rule</param>
|
||||
/// <param name="uriMatchPart">Indicates whether the full URI or the path should be evaluated for URL segments</param>
|
||||
/// <exception cref="FormatException">Thrown when the server variable is unknown</exception>
|
||||
/// <returns>The matching <see cref="PatternSegment"/></returns>
|
||||
public static PatternSegment FindServerVariable(string serverVariable, ParserContext context, bool global)
|
||||
public static PatternSegment FindServerVariable(string serverVariable, ParserContext context, UriMatchPart uriMatchPart)
|
||||
{
|
||||
switch (serverVariable)
|
||||
{
|
||||
|
|
@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
case "HTTP_CONNECTION":
|
||||
return new HeaderSegment(HeaderNames.Connection);
|
||||
case "HTTP_URL":
|
||||
return global ? (PatternSegment)new GlobalRuleUrlSegment() : (PatternSegment)new UrlSegment();
|
||||
return new UrlSegment(uriMatchPart);
|
||||
case "HTTPS":
|
||||
return new IsHttpsUrlSegment();
|
||||
case "LOCAL_ADDR":
|
||||
|
|
@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
case "REQUEST_FILENAME":
|
||||
return new RequestFileNameSegment();
|
||||
case "REQUEST_URI":
|
||||
return global ? (PatternSegment)new GlobalRuleUrlSegment() : (PatternSegment)new UrlSegment();
|
||||
return new UrlSegment(uriMatchPart);
|
||||
default:
|
||||
throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(serverVariable, context.Index));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
// 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.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
||||
{
|
||||
public class UriMatchCondition : Condition
|
||||
{
|
||||
public UriMatchCondition(InputParser inputParser, string input, string pattern, UriMatchPart uriMatchPart, bool ignoreCase, bool negate)
|
||||
{
|
||||
var regex = new Regex(
|
||||
pattern,
|
||||
ignoreCase ? RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase : RegexOptions.CultureInvariant | RegexOptions.Compiled,
|
||||
TimeSpan.FromMilliseconds(1));
|
||||
Input = inputParser.ParseInputString(input, uriMatchPart);
|
||||
Match = new RegexMatch(regex, negate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// 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.IISUrlRewrite
|
||||
{
|
||||
public enum UriMatchPart
|
||||
{
|
||||
Full,
|
||||
Path
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlActions;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
||||
{
|
||||
|
|
@ -45,17 +46,17 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
|
||||
foreach (var rule in rules.Elements(RewriteTags.Rule))
|
||||
{
|
||||
var builder = new UrlRewriteRuleBuilder();
|
||||
ParseRuleAttributes(rule, builder, global);
|
||||
var builder = new UrlRewriteRuleBuilder { Global = global };
|
||||
ParseRuleAttributes(rule, builder);
|
||||
|
||||
if (builder.Enabled)
|
||||
{
|
||||
result.Add(builder.Build(global));
|
||||
result.Add(builder.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseRuleAttributes(XElement rule, UrlRewriteRuleBuilder builder, bool global)
|
||||
private void ParseRuleAttributes(XElement rule, UrlRewriteRuleBuilder builder)
|
||||
{
|
||||
builder.Name = rule.Attribute(RewriteTags.Name)?.Value;
|
||||
|
||||
|
|
@ -84,8 +85,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
}
|
||||
|
||||
ParseMatch(match, builder, patternSyntax);
|
||||
ParseConditions(rule.Element(RewriteTags.Conditions), builder, patternSyntax, global);
|
||||
ParseUrlAction(action, builder, stopProcessing, global);
|
||||
ParseConditions(rule.Element(RewriteTags.Conditions), builder, patternSyntax);
|
||||
ParseUrlAction(action, builder, stopProcessing);
|
||||
}
|
||||
|
||||
private void ParseMatch(XElement match, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)
|
||||
|
|
@ -101,7 +102,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
builder.AddUrlMatch(parsedInputString, ignoreCase, negate, patternSyntax);
|
||||
}
|
||||
|
||||
private void ParseConditions(XElement conditions, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax, bool global)
|
||||
private void ParseConditions(XElement conditions, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)
|
||||
{
|
||||
if (conditions == null)
|
||||
{
|
||||
|
|
@ -110,32 +111,76 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
|
||||
var grouping = ParseEnum(conditions, RewriteTags.LogicalGrouping, LogicalGrouping.MatchAll);
|
||||
var trackAllCaptures = ParseBool(conditions, RewriteTags.TrackAllCaptures, defaultValue: false);
|
||||
builder.AddUrlConditions(grouping, trackAllCaptures);
|
||||
builder.ConfigureConditionBehavior(grouping, trackAllCaptures);
|
||||
|
||||
foreach (var cond in conditions.Elements(RewriteTags.Add))
|
||||
{
|
||||
ParseCondition(cond, builder, patternSyntax, trackAllCaptures, global);
|
||||
ParseCondition(cond, builder, patternSyntax);
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseCondition(XElement condition, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax, bool trackAllCaptures, bool global)
|
||||
private void ParseCondition(XElement conditionElement, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)
|
||||
{
|
||||
var ignoreCase = ParseBool(condition, RewriteTags.IgnoreCase, defaultValue: true);
|
||||
var negate = ParseBool(condition, RewriteTags.Negate, defaultValue: false);
|
||||
var matchType = ParseEnum(condition, RewriteTags.MatchType, MatchType.Pattern);
|
||||
var parsedInputString = condition.Attribute(RewriteTags.Input)?.Value;
|
||||
var ignoreCase = ParseBool(conditionElement, RewriteTags.IgnoreCase, defaultValue: true);
|
||||
var negate = ParseBool(conditionElement, RewriteTags.Negate, defaultValue: false);
|
||||
var matchType = ParseEnum(conditionElement, RewriteTags.MatchType, MatchType.Pattern);
|
||||
var parsedInputString = conditionElement.Attribute(RewriteTags.Input)?.Value;
|
||||
|
||||
if (parsedInputString == null)
|
||||
{
|
||||
throw new InvalidUrlRewriteFormatException(condition, "Conditions must have an input attribute");
|
||||
throw new InvalidUrlRewriteFormatException(conditionElement, "Conditions must have an input attribute");
|
||||
}
|
||||
|
||||
var parsedPatternString = condition.Attribute(RewriteTags.Pattern)?.Value;
|
||||
var input = _inputParser.ParseInputString(parsedInputString, global);
|
||||
builder.AddUrlCondition(input, parsedPatternString, patternSyntax, matchType, ignoreCase, negate, trackAllCaptures);
|
||||
var parsedPatternString = conditionElement.Attribute(RewriteTags.Pattern)?.Value;
|
||||
Condition condition;
|
||||
|
||||
switch (patternSyntax)
|
||||
{
|
||||
case PatternSyntax.ECMAScript:
|
||||
{
|
||||
switch (matchType)
|
||||
{
|
||||
case MatchType.Pattern:
|
||||
{
|
||||
if (string.IsNullOrEmpty(parsedPatternString))
|
||||
{
|
||||
throw new FormatException("Match does not have an associated pattern attribute in condition");
|
||||
}
|
||||
condition = new UriMatchCondition(_inputParser, parsedInputString, parsedPatternString, builder.UriMatchPart, ignoreCase, negate);
|
||||
break;
|
||||
}
|
||||
case MatchType.IsDirectory:
|
||||
{
|
||||
condition = new Condition { Input = _inputParser.ParseInputString(parsedInputString, builder.UriMatchPart), Match = new IsDirectoryMatch(negate) };
|
||||
break;
|
||||
}
|
||||
case MatchType.IsFile:
|
||||
{
|
||||
condition = new Condition { Input = _inputParser.ParseInputString(parsedInputString, builder.UriMatchPart), Match = new IsFileMatch(negate) };
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new FormatException("Unrecognized matchType");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PatternSyntax.Wildcard:
|
||||
throw new NotSupportedException("Wildcard syntax is not supported");
|
||||
case PatternSyntax.ExactMatch:
|
||||
if (string.IsNullOrEmpty(parsedPatternString))
|
||||
{
|
||||
throw new FormatException("Match does not have an associated pattern attribute in condition");
|
||||
}
|
||||
condition = new Condition { Input = _inputParser.ParseInputString(parsedInputString, builder.UriMatchPart), Match = new ExactMatch(ignoreCase, parsedPatternString, negate) };
|
||||
break;
|
||||
default:
|
||||
throw new FormatException("Unrecognized pattern syntax");
|
||||
}
|
||||
|
||||
builder.AddUrlCondition(condition);
|
||||
}
|
||||
|
||||
private void ParseUrlAction(XElement urlAction, UrlRewriteRuleBuilder builder, bool stopProcessing, bool global)
|
||||
private void ParseUrlAction(XElement urlAction, UrlRewriteRuleBuilder builder, bool stopProcessing)
|
||||
{
|
||||
var actionType = ParseEnum(urlAction, RewriteTags.Type, ActionType.None);
|
||||
UrlAction action;
|
||||
|
|
@ -156,7 +201,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
}
|
||||
}
|
||||
|
||||
var urlPattern = _inputParser.ParseInputString(url, global);
|
||||
var urlPattern = _inputParser.ParseInputString(url, builder.UriMatchPart);
|
||||
var appendQuery = ParseBool(urlAction, RewriteTags.AppendQueryString, defaultValue: true);
|
||||
|
||||
if (actionType == ActionType.Rewrite)
|
||||
|
|
|
|||
|
|
@ -14,21 +14,21 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
|
||||
public string Name { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public bool Global { get; set; }
|
||||
public UriMatchPart UriMatchPart => Global ? UriMatchPart.Full : UriMatchPart.Path;
|
||||
|
||||
private UrlMatch _initialMatch;
|
||||
private IList<Condition> _conditions;
|
||||
private ConditionCollection _conditions;
|
||||
private UrlAction _action;
|
||||
private bool _matchAny;
|
||||
private bool _trackAllCaptures;
|
||||
|
||||
public IISUrlRewriteRule Build(bool global)
|
||||
public IISUrlRewriteRule Build()
|
||||
{
|
||||
if (_initialMatch == null || _action == null)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot create UrlRewriteRule without action and match");
|
||||
}
|
||||
|
||||
return new IISUrlRewriteRule(Name, _initialMatch, _conditions, _action, _trackAllCaptures, global);
|
||||
return new IISUrlRewriteRule(Name, _initialMatch, _conditions, _action, Global);
|
||||
}
|
||||
|
||||
public void AddUrlAction(UrlAction action)
|
||||
|
|
@ -66,70 +66,31 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
}
|
||||
}
|
||||
|
||||
public void AddUrlCondition(Pattern input, string pattern, PatternSyntax patternSyntax, MatchType matchType, bool ignoreCase, bool negate, bool trackAllCaptures)
|
||||
public void ConfigureConditionBehavior(LogicalGrouping logicalGrouping, bool trackAllCaptures)
|
||||
{
|
||||
_conditions = new ConditionCollection(logicalGrouping, trackAllCaptures);
|
||||
}
|
||||
|
||||
public void AddUrlCondition(Condition condition)
|
||||
{
|
||||
// If there are no conditions specified
|
||||
if (_conditions == null)
|
||||
{
|
||||
AddUrlConditions(LogicalGrouping.MatchAll, trackAllCaptures);
|
||||
throw new InvalidOperationException($"You must first configure condition behavior by calling {nameof(ConfigureConditionBehavior)}");
|
||||
}
|
||||
|
||||
switch (patternSyntax)
|
||||
if (condition == null)
|
||||
{
|
||||
case PatternSyntax.ECMAScript:
|
||||
{
|
||||
switch (matchType)
|
||||
{
|
||||
case MatchType.Pattern:
|
||||
{
|
||||
if (string.IsNullOrEmpty(pattern))
|
||||
{
|
||||
throw new FormatException("Match does not have an associated pattern attribute in condition");
|
||||
}
|
||||
|
||||
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.Add(new Condition { Input = input, Match = new IsDirectoryMatch(negate), OrNext = _matchAny });
|
||||
break;
|
||||
}
|
||||
case MatchType.IsFile:
|
||||
{
|
||||
_conditions.Add(new Condition { Input = input, Match = new IsFileMatch(negate), OrNext = _matchAny });
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new FormatException("Unrecognized matchType");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PatternSyntax.Wildcard:
|
||||
throw new NotSupportedException("Wildcard syntax is not supported");
|
||||
case PatternSyntax.ExactMatch:
|
||||
if (pattern == null)
|
||||
{
|
||||
throw new FormatException("Match does not have an associated pattern attribute in condition");
|
||||
}
|
||||
_conditions.Add(new Condition { Input = input, Match = new ExactMatch(ignoreCase, pattern, negate), OrNext = _matchAny });
|
||||
break;
|
||||
default:
|
||||
throw new FormatException("Unrecognized pattern syntax");
|
||||
throw new ArgumentNullException(nameof(condition));
|
||||
}
|
||||
_conditions.Add(condition);
|
||||
}
|
||||
|
||||
public void AddUrlConditions(LogicalGrouping logicalGrouping, bool trackAllCaptures)
|
||||
public void AddUrlConditions(IEnumerable<Condition> conditions)
|
||||
{
|
||||
_conditions = new List<Condition>();
|
||||
_matchAny = logicalGrouping == LogicalGrouping.MatchAny;
|
||||
_trackAllCaptures = trackAllCaptures;
|
||||
if (_conditions == null)
|
||||
{
|
||||
throw new InvalidOperationException($"You must first configure condition behavior by calling {nameof(ConfigureConditionBehavior)}");
|
||||
}
|
||||
_conditions.AddConditions(conditions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +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.Extensions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
||||
{
|
||||
public class GlobalRuleUrlSegment : PatternSegment
|
||||
{
|
||||
public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)
|
||||
{
|
||||
return context.HttpContext.Request.GetEncodedUrl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +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.Extensions;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
||||
{
|
||||
public class UrlSegment : PatternSegment
|
||||
{
|
||||
private readonly UriMatchPart _uriMatchPart;
|
||||
|
||||
public UrlSegment()
|
||||
: this(UriMatchPart.Path)
|
||||
{
|
||||
}
|
||||
|
||||
public UrlSegment(UriMatchPart uriMatchPart)
|
||||
{
|
||||
_uriMatchPart = uriMatchPart;
|
||||
}
|
||||
|
||||
public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)
|
||||
{
|
||||
return context.HttpContext.Request.Path;
|
||||
return _uriMatchPart == UriMatchPart.Full ? context.HttpContext.Request.GetEncodedUrl() : (string)context.HttpContext.Request.Path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlActions;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;
|
||||
|
|
@ -29,7 +28,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
</rewrite>";
|
||||
|
||||
var expected = new List<IISUrlRewriteRule>();
|
||||
expected.Add(CreateTestRule(new List<Condition>(),
|
||||
expected.Add(CreateTestRule(new ConditionCollection(),
|
||||
url: "^article/([0-9]+)/([_0-9a-z-]+)",
|
||||
name: "Rewrite to article.aspx",
|
||||
actionType: ActionType.Rewrite,
|
||||
|
|
@ -58,10 +57,10 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
</rules>
|
||||
</rewrite>";
|
||||
|
||||
var condList = new List<Condition>();
|
||||
var condList = new ConditionCollection();
|
||||
condList.Add(new Condition
|
||||
{
|
||||
Input = new InputParser().ParseInputString("{HTTPS}", global: false),
|
||||
Input = new InputParser().ParseInputString("{HTTPS}"),
|
||||
Match = new RegexMatch(new Regex("^OFF$"), false)
|
||||
});
|
||||
|
||||
|
|
@ -102,10 +101,10 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
</rules>
|
||||
</rewrite>";
|
||||
|
||||
var condList = new List<Condition>();
|
||||
var condList = new ConditionCollection();
|
||||
condList.Add(new Condition
|
||||
{
|
||||
Input = new InputParser().ParseInputString("{HTTPS}", global: false),
|
||||
Input = new InputParser().ParseInputString("{HTTPS}"),
|
||||
Match = new RegexMatch(new Regex("^OFF$"), false)
|
||||
});
|
||||
|
||||
|
|
@ -160,9 +159,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
}
|
||||
|
||||
// Creates a rule with appropriate default values of the url rewrite rule.
|
||||
private IISUrlRewriteRule CreateTestRule(List<Condition> conditions,
|
||||
LogicalGrouping condGrouping = LogicalGrouping.MatchAll,
|
||||
bool condTracking = false,
|
||||
private IISUrlRewriteRule CreateTestRule(ConditionCollection conditions,
|
||||
string name = "",
|
||||
bool enabled = true,
|
||||
PatternSyntax patternSyntax = PatternSyntax.ECMAScript,
|
||||
|
|
@ -174,11 +171,17 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
string pattern = "",
|
||||
bool appendQueryString = false,
|
||||
bool rewrittenUrl = false,
|
||||
bool global = false,
|
||||
UriMatchPart uriMatchPart = UriMatchPart.Path,
|
||||
RedirectType redirectType = RedirectType.Permanent
|
||||
)
|
||||
{
|
||||
return new IISUrlRewriteRule(name, new RegexMatch(new Regex("^OFF$"), false), conditions,
|
||||
new RewriteAction(RuleResult.ContinueRules, new InputParser().ParseInputString(url, global: false), queryStringAppend: false), trackAllCaptures: false);
|
||||
return new IISUrlRewriteRule(
|
||||
name,
|
||||
new RegexMatch(new Regex("^OFF$"), negate),
|
||||
conditions,
|
||||
new RewriteAction(RuleResult.ContinueRules, new InputParser().ParseInputString(url, uriMatchPart), queryStringAppend: false),
|
||||
global);
|
||||
}
|
||||
|
||||
// TODO make rules comparable?
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
public void InputParser_ParseLiteralString()
|
||||
{
|
||||
var testString = "hello/hey/what";
|
||||
var result = new InputParser().ParseInputString(testString, global: false);
|
||||
var result = new InputParser().ParseInputString(testString, UriMatchPart.Path);
|
||||
Assert.Equal(1, result.PatternSegments.Count);
|
||||
}
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[InlineData("foo/", 1)]
|
||||
public void InputParser_ParseStringWithBackReference(string testString, int expected)
|
||||
{
|
||||
var result = new InputParser().ParseInputString(testString, global: false);
|
||||
var result = new InputParser().ParseInputString(testString, UriMatchPart.Path);
|
||||
Assert.Equal(expected, result.PatternSegments.Count);
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[InlineData("hey/{R:1}/{C:1}", "hey/foo/foo")]
|
||||
public void EvaluateBackReferenceRule(string testString, string expected)
|
||||
{
|
||||
var middle = new InputParser().ParseInputString(testString, global: false);
|
||||
var middle = new InputParser().ParseInputString(testString, UriMatchPart.Path);
|
||||
var result = middle.Evaluate(CreateTestRewriteContext(), CreateTestRuleBackReferences(), CreateTestCondBackReferences());
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[InlineData("hey/ToLower:/what", "hey/ToLower:/what")]
|
||||
public void EvaluatToLowerRule(string testString, string expected)
|
||||
{
|
||||
var middle = new InputParser().ParseInputString(testString, global: false);
|
||||
var middle = new InputParser().ParseInputString(testString, UriMatchPart.Path);
|
||||
var result = middle.Evaluate(CreateTestRewriteContext(), CreateTestRuleBackReferences(), CreateTestCondBackReferences());
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
|
@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[InlineData("hey/{UrlEncode:<hey>}", "hey/%3Chey%3E")]
|
||||
public void EvaluatUriEncodeRule(string testString, string expected)
|
||||
{
|
||||
var middle = new InputParser().ParseInputString(testString, global: false);
|
||||
var middle = new InputParser().ParseInputString(testString, UriMatchPart.Path);
|
||||
var result = middle.Evaluate(CreateTestRewriteContext(), CreateTestRuleBackReferences(), CreateTestCondBackReferences());
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
|
@ -88,13 +88,13 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[InlineData("{HTTPS")]
|
||||
public void FormatExceptionsOnBadSyntax(string testString)
|
||||
{
|
||||
Assert.Throws<FormatException>(() => new InputParser().ParseInputString(testString, global: false));
|
||||
Assert.Throws<FormatException>(() => new InputParser().ParseInputString(testString, UriMatchPart.Path));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_throw_FormatException_if_no_rewrite_maps_are_defined()
|
||||
{
|
||||
Assert.Throws<FormatException>(() => new InputParser(null).ParseInputString("{apiMap:{R:1}}", global: false));
|
||||
Assert.Throws<FormatException>(() => new InputParser(null).ParseInputString("{apiMap:{R:1}}", UriMatchPart.Path));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
const string undefinedMapName = "apiMap";
|
||||
var map = new IISRewriteMap(definedMapName);
|
||||
var maps = new IISRewriteMapCollection { map };
|
||||
Assert.Throws<FormatException>(() => new InputParser(maps).ParseInputString($"{{{undefinedMapName}:{{R:1}}}}", global: false));
|
||||
Assert.Throws<FormatException>(() => new InputParser(maps).ParseInputString($"{{{undefinedMapName}:{{R:1}}}}", UriMatchPart.Path));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -118,7 +118,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
var maps = new IISRewriteMapCollection { map };
|
||||
|
||||
var inputString = $"{{{expectedMapName}:{{R:1}}}}";
|
||||
var pattern = new InputParser(maps).ParseInputString(inputString, global: false);
|
||||
var pattern = new InputParser(maps).ParseInputString(inputString, UriMatchPart.Path);
|
||||
Assert.Equal(1, pattern.PatternSegments.Count);
|
||||
|
||||
var segment = pattern.PatternSegments.Single();
|
||||
|
|
|
|||
|
|
@ -2,14 +2,19 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlActions;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Xunit;
|
||||
|
|
@ -456,8 +461,9 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Invoke_GlobalRuleConditionMatchesAgainstFullUri()
|
||||
public async Task Invoke_GlobalRuleConditionMatchesAgainstFullUri_ParsedRule()
|
||||
{
|
||||
// arrange
|
||||
var xml = @"<rewrite>
|
||||
<globalRules>
|
||||
<rule name=""Test"" patternSyntax=""ECMAScript"" stopProcessing=""true"">
|
||||
|
|
@ -478,8 +484,10 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
});
|
||||
var server = new TestServer(builder);
|
||||
|
||||
// act
|
||||
var response = await server.CreateClient().GetStringAsync($"http://localhost/{Guid.NewGuid()}/foo/bar");
|
||||
|
||||
// assert
|
||||
Assert.Equal("http://www.test.com/foo/bar", response);
|
||||
}
|
||||
|
||||
|
|
@ -543,5 +551,52 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
Assert.Equal("reason", response.ReasonPhrase);
|
||||
Assert.Equal("description", content);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"^http://localhost(/.*)", "http://localhost/foo/bar", UriMatchPart.Path)]
|
||||
[InlineData(@"^http://localhost(/.*)", "http://www.test.com/foo/bar", UriMatchPart.Full)]
|
||||
public async Task Invoke_GlobalRuleConditionMatchesAgainstFullUri_CodedRule(string conditionInputPattern, string expectedResult, UriMatchPart uriMatchPart)
|
||||
{
|
||||
// arrange
|
||||
var inputParser = new InputParser();
|
||||
|
||||
var ruleBuilder = new UrlRewriteRuleBuilder
|
||||
{
|
||||
Name = "test",
|
||||
Global = false
|
||||
};
|
||||
ruleBuilder.AddUrlMatch(".*");
|
||||
|
||||
var condition = new UriMatchCondition(
|
||||
inputParser,
|
||||
"{REQUEST_URI}",
|
||||
conditionInputPattern,
|
||||
uriMatchPart,
|
||||
ignoreCase: true,
|
||||
negate: false);
|
||||
ruleBuilder.ConfigureConditionBehavior(LogicalGrouping.MatchAll, trackAllCaptures: true);
|
||||
ruleBuilder.AddUrlCondition(condition);
|
||||
|
||||
var action = new RewriteAction(
|
||||
RuleResult.SkipRemainingRules,
|
||||
inputParser.ParseInputString(@"http://www.test.com{C:1}", uriMatchPart),
|
||||
queryStringAppend: false);
|
||||
ruleBuilder.AddUrlAction(action);
|
||||
|
||||
var options = new RewriteOptions().Add(ruleBuilder.Build());
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRewriter(options);
|
||||
app.Run(context => context.Response.WriteAsync(context.Request.GetEncodedUrl()));
|
||||
});
|
||||
var server = new TestServer(builder);
|
||||
|
||||
// act
|
||||
var response = await server.CreateClient().GetStringAsync("http://localhost/foo/bar");
|
||||
|
||||
// assert
|
||||
Assert.Equal(expectedResult, response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,25 +13,25 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
public class ServerVariableTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("CONTENT_LENGTH", "10", false)]
|
||||
[InlineData("CONTENT_TYPE", "json", false)]
|
||||
[InlineData("HTTP_ACCEPT", "accept", false)]
|
||||
[InlineData("HTTP_COOKIE", "cookie", false)]
|
||||
[InlineData("HTTP_HOST", "example.com", false)]
|
||||
[InlineData("HTTP_REFERER", "referer", false)]
|
||||
[InlineData("HTTP_USER_AGENT", "useragent", false)]
|
||||
[InlineData("HTTP_CONNECTION", "connection", false)]
|
||||
[InlineData("HTTP_URL", "/foo", false)]
|
||||
[InlineData("HTTP_URL", "http://example.com/foo?bar=1", true)]
|
||||
[InlineData("QUERY_STRING", "bar=1", false)]
|
||||
[InlineData("REQUEST_FILENAME", "/foo", false)]
|
||||
[InlineData("REQUEST_URI", "/foo", false)]
|
||||
[InlineData("REQUEST_URI", "http://example.com/foo?bar=1", true)]
|
||||
public void CheckServerVariableParsingAndApplication(string variable, string expected, bool global)
|
||||
[InlineData("CONTENT_LENGTH", "10", UriMatchPart.Path)]
|
||||
[InlineData("CONTENT_TYPE", "json", UriMatchPart.Path)]
|
||||
[InlineData("HTTP_ACCEPT", "accept", UriMatchPart.Path)]
|
||||
[InlineData("HTTP_COOKIE", "cookie", UriMatchPart.Path)]
|
||||
[InlineData("HTTP_HOST", "example.com", UriMatchPart.Path)]
|
||||
[InlineData("HTTP_REFERER", "referer", UriMatchPart.Path)]
|
||||
[InlineData("HTTP_USER_AGENT", "useragent", UriMatchPart.Path)]
|
||||
[InlineData("HTTP_CONNECTION", "connection", UriMatchPart.Path)]
|
||||
[InlineData("HTTP_URL", "/foo", UriMatchPart.Path)]
|
||||
[InlineData("HTTP_URL", "http://example.com/foo?bar=1", UriMatchPart.Full)]
|
||||
[InlineData("QUERY_STRING", "bar=1", UriMatchPart.Path)]
|
||||
[InlineData("REQUEST_FILENAME", "/foo", UriMatchPart.Path)]
|
||||
[InlineData("REQUEST_URI", "/foo", UriMatchPart.Path)]
|
||||
[InlineData("REQUEST_URI", "http://example.com/foo?bar=1", UriMatchPart.Full)]
|
||||
public void CheckServerVariableParsingAndApplication(string variable, string expected, UriMatchPart uriMatchPart)
|
||||
{
|
||||
// Arrange and Act
|
||||
var testParserContext = new ParserContext("test");
|
||||
var serverVar = ServerVariables.FindServerVariable(variable, testParserContext, global);
|
||||
var serverVar = ServerVariables.FindServerVariable(variable, testParserContext, uriMatchPart);
|
||||
var lookup = serverVar.Evaluate(CreateTestHttpContext(), CreateTestRuleMatch().BackReferences, CreateTestCondMatch().BackReferences);
|
||||
// Assert
|
||||
Assert.Equal(expected, lookup);
|
||||
|
|
@ -72,7 +72,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
var context = new DefaultHttpContext();
|
||||
var rewriteContext = new RewriteContext { HttpContext = context };
|
||||
var testParserContext = new ParserContext("test");
|
||||
var serverVar = ServerVariables.FindServerVariable("QUERY_STRING", testParserContext, global: false);
|
||||
var serverVar = ServerVariables.FindServerVariable("QUERY_STRING", testParserContext, UriMatchPart.Path);
|
||||
var lookup = serverVar.Evaluate(rewriteContext, CreateTestRuleMatch().BackReferences, CreateTestCondMatch().BackReferences);
|
||||
|
||||
Assert.Equal(string.Empty, lookup);
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
var rules = new UrlRewriteFileParser().Parse(xml);
|
||||
|
||||
Assert.Equal(rules.Count, 1);
|
||||
Assert.True(rules[0].TrackAllCaptures);
|
||||
Assert.True(rules[0].Conditions.TrackAllCaptures);
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
rules.FirstOrDefault().ApplyRule(context);
|
||||
Assert.Equal(RuleResult.ContinueRules, context.Result);
|
||||
|
|
|
|||
|
|
@ -1,47 +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;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class GlobalRuleUrlSegmentTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("http", "localhost", 80, null, null, "http://localhost:80/")]
|
||||
[InlineData("http", "localhost", 80, "/foo/bar", null, "http://localhost:80/foo/bar")]
|
||||
[InlineData("http", "localhost", 80, "/foo bar", null, "http://localhost:80/foo%20bar")]
|
||||
[InlineData("http", "localhost", 81, "/foo/bar", null, "http://localhost:81/foo/bar")]
|
||||
[InlineData("http", "localhost", 80, null, "?foo=bar", "http://localhost:80/?foo=bar")]
|
||||
[InlineData("https", "localhost", 443, "/foo/bar", null, "https://localhost:443/foo/bar")]
|
||||
public void AssertSegmentIsCorrect(string scheme, string host, int port, string path, string queryString, string expectedResult)
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Request.Scheme = scheme;
|
||||
httpContext.Request.Host = new HostString(host, port);
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
httpContext.Request.Path = new PathString(path);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(queryString))
|
||||
{
|
||||
httpContext.Request.QueryString = new QueryString(queryString);
|
||||
}
|
||||
|
||||
var context = new RewriteContext { HttpContext = httpContext };
|
||||
context.HttpContext = httpContext;
|
||||
|
||||
// Act
|
||||
var segment = new GlobalRuleUrlSegment();
|
||||
var results = segment.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedResult, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
// 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.IISUrlRewrite;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -10,10 +11,19 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
|||
public class UrlSegmentTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("http", "localhost", 80, "/foo/bar", "/foo/bar")]
|
||||
[InlineData("http", "localhost", 80, "/foo:bar", "/foo:bar")]
|
||||
[InlineData("http", "localhost", 80, "/foo bar", "/foo%20bar")]
|
||||
public void AssertSegmentIsCorrect(string scheme, string host, int port, string path, string expectedResult)
|
||||
[InlineData("http", "localhost", 80, null, UriMatchPart.Path, "")]
|
||||
[InlineData("http", "localhost", 80, "", UriMatchPart.Path, "")]
|
||||
[InlineData("http", "localhost", 80, "/foo/bar", UriMatchPart.Path, "/foo/bar")]
|
||||
[InlineData("http", "localhost", 80, "/foo:bar", UriMatchPart.Path, "/foo:bar")]
|
||||
[InlineData("http", "localhost", 80, "/foo bar", UriMatchPart.Path, "/foo%20bar")]
|
||||
[InlineData("http", "localhost", 80, null, UriMatchPart.Full, "http://localhost:80/")]
|
||||
[InlineData("http", "localhost", 80, "", UriMatchPart.Full, "http://localhost:80/")]
|
||||
[InlineData("http", "localhost", 80, "/foo:bar", UriMatchPart.Full, "http://localhost:80/foo:bar")]
|
||||
[InlineData("http", "localhost", 80, "/foo bar", UriMatchPart.Full, "http://localhost:80/foo%20bar")]
|
||||
[InlineData("http", "localhost", 80, "/foo/bar", UriMatchPart.Full, "http://localhost:80/foo/bar")]
|
||||
[InlineData("http", "localhost", 81, "/foo/bar", UriMatchPart.Full, "http://localhost:81/foo/bar")]
|
||||
[InlineData("https", "localhost", 443, "/foo/bar", UriMatchPart.Full, "https://localhost:443/foo/bar")]
|
||||
public void AssertSegmentIsCorrect(string scheme, string host, int port, string path, UriMatchPart uriMatchPart, string expectedResult)
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
|
|
@ -25,7 +35,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
|||
context.HttpContext = httpContext;
|
||||
|
||||
// Act
|
||||
var segment = new UrlSegment();
|
||||
var segment = new UrlSegment(uriMatchPart);
|
||||
var results = segment.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
|
|
|
|||
Loading…
Reference in New Issue