Added support for IIS global rules (#169)
This commit is contained in:
parent
24a95f6c5d
commit
4fa6ed3792
|
|
@ -14,18 +14,30 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
public IList<Condition> 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)
|
||||
{
|
||||
}
|
||||
|
||||
public IISUrlRewriteRule(string name,
|
||||
UrlMatch initialMatch,
|
||||
IList<Condition> conditions,
|
||||
UrlAction action,
|
||||
bool trackAllCaptures,
|
||||
bool global)
|
||||
{
|
||||
Name = name;
|
||||
InitialMatch = initialMatch;
|
||||
Conditions = conditions;
|
||||
Action = action;
|
||||
TrackAllCaptures = trackAllCaptures;
|
||||
Global = global;
|
||||
}
|
||||
|
||||
public virtual void ApplyRule(RewriteContext context)
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@ 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)
|
||||
public Pattern ParseInputString(string testString, bool global)
|
||||
{
|
||||
if (testString == null)
|
||||
{
|
||||
|
|
@ -27,10 +28,10 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
}
|
||||
|
||||
var context = new ParserContext(testString);
|
||||
return ParseString(context);
|
||||
return ParseString(context, global);
|
||||
}
|
||||
|
||||
private static Pattern ParseString(ParserContext context)
|
||||
private static Pattern ParseString(ParserContext context, bool global)
|
||||
{
|
||||
var results = new List<PatternSegment>();
|
||||
while (context.Next())
|
||||
|
|
@ -43,7 +44,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
// missing {
|
||||
throw new FormatException(Resources.FormatError_InputParserMissingCloseBrace(context.Index));
|
||||
}
|
||||
ParseParameter(context, results);
|
||||
ParseParameter(context, results, global);
|
||||
}
|
||||
else if (context.Current == CloseBrace)
|
||||
{
|
||||
|
|
@ -59,7 +60,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
return new Pattern(results);
|
||||
}
|
||||
|
||||
private static void ParseParameter(ParserContext context, IList<PatternSegment> results)
|
||||
private static void ParseParameter(ParserContext context, IList<PatternSegment> results, bool global)
|
||||
{
|
||||
context.Mark();
|
||||
// Four main cases:
|
||||
|
|
@ -75,7 +76,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));
|
||||
results.Add(ServerVariables.FindServerVariable(parameter, context, global));
|
||||
return;
|
||||
}
|
||||
else if (context.Current == Colon)
|
||||
|
|
@ -87,7 +88,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
{
|
||||
case "ToLower":
|
||||
{
|
||||
var pattern = ParseString(context);
|
||||
var pattern = ParseString(context, global);
|
||||
results.Add(new ToLowerSegment(pattern));
|
||||
|
||||
// at this point, we expect our context to be on the ending closing brace,
|
||||
|
|
@ -105,7 +106,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
}
|
||||
case "UrlEncode":
|
||||
{
|
||||
var pattern = ParseString(context);
|
||||
var pattern = ParseString(context, global);
|
||||
results.Add(new UrlEncodeSegment(pattern));
|
||||
|
||||
if (context.Current != CloseBrace)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,15 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
{
|
||||
public static class ServerVariables
|
||||
{
|
||||
public static PatternSegment FindServerVariable(string serverVariable, ParserContext context)
|
||||
/// <summary>
|
||||
/// Returns the matching <see cref="PatternSegment"/> for the given <paramref name="serverVariable"/>
|
||||
/// </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>
|
||||
/// <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)
|
||||
{
|
||||
switch (serverVariable)
|
||||
{
|
||||
|
|
@ -35,7 +43,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
case "HTTP_CONNECTION":
|
||||
return new HeaderSegment(HeaderNames.Connection);
|
||||
case "HTTP_URL":
|
||||
return new UrlSegment();
|
||||
return global ? (PatternSegment)new GlobalRuleUrlSegment() : (PatternSegment)new UrlSegment();
|
||||
case "HTTPS":
|
||||
return new IsHttpsUrlSegment();
|
||||
case "LOCAL_ADDR":
|
||||
|
|
@ -53,7 +61,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
case "REQUEST_FILENAME":
|
||||
return new RequestFileNameSegment();
|
||||
case "REQUEST_URI":
|
||||
return new UrlSegment();
|
||||
return global ? (PatternSegment)new GlobalRuleUrlSegment() : (PatternSegment)new UrlSegment();
|
||||
default:
|
||||
throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(serverVariable, context.Index));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,40 +22,33 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
if (xmlRoot != null)
|
||||
{
|
||||
var result = new List<IISUrlRewriteRule>();
|
||||
// TODO Global rules are currently not treated differently than normal rules, fix.
|
||||
// See: https://github.com/aspnet/BasicMiddleware/issues/59
|
||||
ParseRules(xmlRoot.Descendants(RewriteTags.GlobalRules).FirstOrDefault(), result);
|
||||
ParseRules(xmlRoot.Descendants(RewriteTags.Rules).FirstOrDefault(), result);
|
||||
ParseRules(xmlRoot.Descendants(RewriteTags.GlobalRules).FirstOrDefault(), result, global: true);
|
||||
ParseRules(xmlRoot.Descendants(RewriteTags.Rules).FirstOrDefault(), result, global: false);
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ParseRules(XElement rules, IList<IISUrlRewriteRule> result)
|
||||
private void ParseRules(XElement rules, IList<IISUrlRewriteRule> result, bool global)
|
||||
{
|
||||
if (rules == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.Equals(rules.Name.ToString(), "GlobalRules", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new NotSupportedException("Support for global rules has not been implemented yet");
|
||||
}
|
||||
|
||||
foreach (var rule in rules.Elements(RewriteTags.Rule))
|
||||
{
|
||||
var builder = new UrlRewriteRuleBuilder();
|
||||
ParseRuleAttributes(rule, builder);
|
||||
ParseRuleAttributes(rule, builder, global);
|
||||
|
||||
if (builder.Enabled)
|
||||
{
|
||||
result.Add(builder.Build());
|
||||
result.Add(builder.Build(global));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseRuleAttributes(XElement rule, UrlRewriteRuleBuilder builder)
|
||||
private void ParseRuleAttributes(XElement rule, UrlRewriteRuleBuilder builder, bool global)
|
||||
{
|
||||
builder.Name = rule.Attribute(RewriteTags.Name)?.Value;
|
||||
|
||||
|
|
@ -84,8 +77,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
}
|
||||
|
||||
ParseMatch(match, builder, patternSyntax);
|
||||
ParseConditions(rule.Element(RewriteTags.Conditions), builder, patternSyntax);
|
||||
ParseUrlAction(action, builder, stopProcessing);
|
||||
ParseConditions(rule.Element(RewriteTags.Conditions), builder, patternSyntax, global);
|
||||
ParseUrlAction(action, builder, stopProcessing, global);
|
||||
}
|
||||
|
||||
private void ParseMatch(XElement match, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)
|
||||
|
|
@ -101,7 +94,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
builder.AddUrlMatch(parsedInputString, ignoreCase, negate, patternSyntax);
|
||||
}
|
||||
|
||||
private void ParseConditions(XElement conditions, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)
|
||||
private void ParseConditions(XElement conditions, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax, bool global)
|
||||
{
|
||||
if (conditions == null)
|
||||
{
|
||||
|
|
@ -114,11 +107,11 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
|
||||
foreach (var cond in conditions.Elements(RewriteTags.Add))
|
||||
{
|
||||
ParseCondition(cond, builder, patternSyntax, trackAllCaptures);
|
||||
ParseCondition(cond, builder, patternSyntax, trackAllCaptures, global);
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseCondition(XElement condition, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax, bool trackAllCaptures)
|
||||
private void ParseCondition(XElement condition, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax, bool trackAllCaptures, bool global)
|
||||
{
|
||||
var ignoreCase = ParseBool(condition, RewriteTags.IgnoreCase, defaultValue: true);
|
||||
var negate = ParseBool(condition, RewriteTags.Negate, defaultValue: false);
|
||||
|
|
@ -133,7 +126,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
var parsedPatternString = condition.Attribute(RewriteTags.Pattern)?.Value;
|
||||
try
|
||||
{
|
||||
var input = _inputParser.ParseInputString(parsedInputString);
|
||||
var input = _inputParser.ParseInputString(parsedInputString, global);
|
||||
builder.AddUrlCondition(input, parsedPatternString, patternSyntax, matchType, ignoreCase, negate, trackAllCaptures);
|
||||
}
|
||||
catch (FormatException formatException)
|
||||
|
|
@ -142,7 +135,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
}
|
||||
}
|
||||
|
||||
private void ParseUrlAction(XElement urlAction, UrlRewriteRuleBuilder builder, bool stopProcessing)
|
||||
private void ParseUrlAction(XElement urlAction, UrlRewriteRuleBuilder builder, bool stopProcessing, bool global)
|
||||
{
|
||||
var actionType = ParseEnum(urlAction, RewriteTags.Type, ActionType.None);
|
||||
var redirectType = ParseEnum(urlAction, RewriteTags.RedirectType, RedirectType.Permanent);
|
||||
|
|
@ -160,7 +153,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
|
||||
try
|
||||
{
|
||||
var input = _inputParser.ParseInputString(url);
|
||||
var input = _inputParser.ParseInputString(url, global);
|
||||
builder.AddUrlAction(input, actionType, appendQuery, stopProcessing, (int)redirectType);
|
||||
}
|
||||
catch (FormatException formatException)
|
||||
|
|
|
|||
|
|
@ -23,14 +23,14 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite
|
|||
private bool _matchAny;
|
||||
private bool _trackAllCaptures;
|
||||
|
||||
public IISUrlRewriteRule Build()
|
||||
public IISUrlRewriteRule Build(bool global)
|
||||
{
|
||||
if (_initialMatch == null || _action == null)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot create UrlRewriteRule without action and match");
|
||||
}
|
||||
|
||||
return new IISUrlRewriteRule(Name, _initialMatch, _conditions, _action, _trackAllCaptures);
|
||||
return new IISUrlRewriteRule(Name, _initialMatch, _conditions, _action, _trackAllCaptures, global);
|
||||
}
|
||||
|
||||
public void AddUrlAction(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,4 +10,4 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
|||
return context.HttpContext.Request.Path;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,8 @@ using System;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;
|
||||
using Microsoft.AspNetCore.Rewrite.Logging;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
|
@ -75,11 +77,10 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
foreach (var rule in _options.Rules)
|
||||
{
|
||||
rule.ApplyRule(rewriteContext);
|
||||
var currentUrl = new Lazy<string>(() => context.Request.Path + context.Request.QueryString);
|
||||
switch (rewriteContext.Result)
|
||||
{
|
||||
case RuleResult.ContinueRules:
|
||||
_logger.RewriteMiddlewareRequestContinueResults(currentUrl.Value);
|
||||
_logger.RewriteMiddlewareRequestContinueResults(context.Request.GetEncodedUrl());
|
||||
break;
|
||||
case RuleResult.EndResponse:
|
||||
_logger.RewriteMiddlewareRequestResponseComplete(
|
||||
|
|
@ -87,7 +88,7 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
context.Response.StatusCode);
|
||||
return TaskCache.CompletedTask;
|
||||
case RuleResult.SkipRemainingRules:
|
||||
_logger.RewriteMiddlewareRequestStopRules(currentUrl.Value);
|
||||
_logger.RewriteMiddlewareRequestStopRules(context.Request.GetEncodedUrl());
|
||||
return _next(context);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException($"Invalid rule termination {rewriteContext.Result}");
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
var condList = new List<Condition>();
|
||||
condList.Add(new Condition
|
||||
{
|
||||
Input = new InputParser().ParseInputString("{HTTPS}"),
|
||||
Input = new InputParser().ParseInputString("{HTTPS}", global: false),
|
||||
Match = new RegexMatch(new Regex("^OFF$"), false)
|
||||
});
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
var condList = new List<Condition>();
|
||||
condList.Add(new Condition
|
||||
{
|
||||
Input = new InputParser().ParseInputString("{HTTPS}"),
|
||||
Input = new InputParser().ParseInputString("{HTTPS}", global: false),
|
||||
Match = new RegexMatch(new Regex("^OFF$"), false)
|
||||
});
|
||||
|
||||
|
|
@ -128,6 +128,37 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
AssertUrlRewriteRuleEquality(expected, res);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_parse_global_rules()
|
||||
{
|
||||
// arrange
|
||||
var xml = @"<rewrite>
|
||||
<globalRules>
|
||||
<rule name=""httpsOnly"" patternSyntax=""ECMAScript"" stopProcessing=""true"">
|
||||
<match url="".*"" />
|
||||
<conditions logicalGrouping=""MatchAll"" trackAllCaptures=""false"">
|
||||
<add input=""{HTTPS}"" pattern=""off"" />
|
||||
</conditions>
|
||||
<action type=""Redirect"" url=""https://{HTTP_HOST}{REQUEST_URI}"" />
|
||||
</rule>
|
||||
</globalRules>
|
||||
<rules>
|
||||
<rule name=""Rewrite to article.aspx"">
|
||||
<match url = ""^article/([0-9]+)/([_0-9a-z-]+)"" />
|
||||
<action type=""Rewrite"" url =""article.aspx?id={R:1}&title={R:2}"" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>";
|
||||
|
||||
// act
|
||||
var rules = new UrlRewriteFileParser().Parse(new StringReader(xml));
|
||||
|
||||
// assert
|
||||
Assert.Equal(2, rules.Count);
|
||||
Assert.True(rules[0].Global);
|
||||
Assert.False(rules[1].Global);
|
||||
}
|
||||
|
||||
// Creates a rule with appropriate default values of the url rewrite rule.
|
||||
private IISUrlRewriteRule CreateTestRule(List<Condition> conditions,
|
||||
LogicalGrouping condGrouping = LogicalGrouping.MatchAll,
|
||||
|
|
@ -147,7 +178,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
)
|
||||
{
|
||||
return new IISUrlRewriteRule(name, new RegexMatch(new Regex("^OFF$"), false), conditions,
|
||||
new RewriteAction(RuleResult.ContinueRules, new InputParser().ParseInputString(url), queryStringAppend: false), trackAllCaptures: false);
|
||||
new RewriteAction(RuleResult.ContinueRules, new InputParser().ParseInputString(url, global: false), queryStringAppend: false), trackAllCaptures: false);
|
||||
}
|
||||
|
||||
// TODO make rules comparable?
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
public void InputParser_ParseLiteralString()
|
||||
{
|
||||
var testString = "hello/hey/what";
|
||||
var result = new InputParser().ParseInputString(testString);
|
||||
var result = new InputParser().ParseInputString(testString, global: false);
|
||||
Assert.Equal(1, result.PatternSegments.Count);
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[InlineData("foo/", 1)]
|
||||
public void InputParser_ParseStringWithBackReference(string testString, int expected)
|
||||
{
|
||||
var result = new InputParser().ParseInputString(testString);
|
||||
var result = new InputParser().ParseInputString(testString, global: false);
|
||||
Assert.Equal(expected, result.PatternSegments.Count);
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +44,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);
|
||||
var middle = new InputParser().ParseInputString(testString, global: false);
|
||||
var result = middle.Evaluate(CreateTestRewriteContext(), CreateTestRuleBackReferences(), CreateTestCondBackReferences());
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
|
@ -57,7 +57,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);
|
||||
var middle = new InputParser().ParseInputString(testString, global: false);
|
||||
var result = middle.Evaluate(CreateTestRewriteContext(), CreateTestRuleBackReferences(), CreateTestCondBackReferences());
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
|
@ -66,7 +66,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);
|
||||
var middle = new InputParser().ParseInputString(testString, global: false);
|
||||
var result = middle.Evaluate(CreateTestRewriteContext(), CreateTestRuleBackReferences(), CreateTestCondBackReferences());
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
|
@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[InlineData("{HTTPS")]
|
||||
public void FormatExceptionsOnBadSyntax(string testString)
|
||||
{
|
||||
Assert.Throws<FormatException>(() => new InputParser().ParseInputString(testString));
|
||||
Assert.Throws<FormatException>(() => new InputParser().ParseInputString(testString, global: false));
|
||||
}
|
||||
|
||||
private RewriteContext CreateTestRewriteContext()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Xunit;
|
||||
|
|
@ -451,5 +452,33 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
|
||||
Assert.Equal("Cannot access back reference at index 9. Only 5 back references were captured.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Invoke_GlobalRuleConditionMatchesAgainstFullUri()
|
||||
{
|
||||
var xml = @"<rewrite>
|
||||
<globalRules>
|
||||
<rule name=""Test"" patternSyntax=""ECMAScript"" stopProcessing=""true"">
|
||||
<match url="".*"" />
|
||||
<conditions logicalGrouping=""MatchAll"" trackAllCaptures=""false"">
|
||||
<add input=""{REQUEST_URI}"" pattern=""^http://localhost/([0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12})(/.*)"" />
|
||||
</conditions>
|
||||
<action type=""Rewrite"" url=""http://www.test.com{C:2}"" />
|
||||
</rule>
|
||||
</globalRules>
|
||||
</rewrite>";
|
||||
var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(xml));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRewriter(options);
|
||||
app.Run(context => context.Response.WriteAsync(context.Request.GetEncodedUrl()));
|
||||
});
|
||||
var server = new TestServer(builder);
|
||||
|
||||
var response = await server.CreateClient().GetStringAsync($"http://localhost/{Guid.NewGuid()}/foo/bar");
|
||||
|
||||
Assert.Equal("http://www.test.com/foo/bar", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,22 +13,25 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
public class ServerVariableTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("CONTENT_LENGTH", "10")]
|
||||
[InlineData("CONTENT_TYPE", "json")]
|
||||
[InlineData("HTTP_ACCEPT", "accept")]
|
||||
[InlineData("HTTP_COOKIE", "cookie")]
|
||||
[InlineData("HTTP_HOST", "example.com")]
|
||||
[InlineData("HTTP_REFERER", "referer")]
|
||||
[InlineData("HTTP_USER_AGENT", "useragent")]
|
||||
[InlineData("HTTP_CONNECTION", "connection")]
|
||||
[InlineData("HTTP_URL", "/foo")]
|
||||
[InlineData("QUERY_STRING", "bar=1")]
|
||||
[InlineData("REQUEST_FILENAME", "/foo")]
|
||||
public void CheckServerVariableParsingAndApplication(string variable, string expected)
|
||||
[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)
|
||||
{
|
||||
// Arrange and Act
|
||||
var testParserContext = new ParserContext("test");
|
||||
var serverVar = ServerVariables.FindServerVariable(variable, testParserContext);
|
||||
var serverVar = ServerVariables.FindServerVariable(variable, testParserContext, global);
|
||||
var lookup = serverVar.Evaluate(CreateTestHttpContext(), CreateTestRuleMatch().BackReferences, CreateTestCondMatch().BackReferences);
|
||||
// Assert
|
||||
Assert.Equal(expected, lookup);
|
||||
|
|
@ -37,6 +40,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
private RewriteContext CreateTestHttpContext()
|
||||
{
|
||||
var context = new DefaultHttpContext();
|
||||
context.Request.Scheme = "http";
|
||||
context.Request.Host = new HostString("example.com");
|
||||
context.Request.Path = PathString.FromUriComponent("/foo");
|
||||
context.Request.QueryString = QueryString.FromUriComponent("?bar=1");
|
||||
|
|
@ -68,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);
|
||||
var serverVar = ServerVariables.FindServerVariable("QUERY_STRING", testParserContext, global: false);
|
||||
var lookup = serverVar.Evaluate(rewriteContext, CreateTestRuleMatch().BackReferences, CreateTestCondMatch().BackReferences);
|
||||
|
||||
Assert.Equal(string.Empty, lookup);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,18 +9,27 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
|||
{
|
||||
public class UrlSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void LocalPortSegment_AssertSegmentIsCorrect()
|
||||
[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)
|
||||
{
|
||||
// Arrange
|
||||
var segement = new UrlSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Request.Path = new PathString("/foo/bar");
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Request.Scheme = scheme;
|
||||
httpContext.Request.Host = new HostString(host, port);
|
||||
httpContext.Request.Path = new PathString(path);
|
||||
|
||||
var context = new RewriteContext { HttpContext = httpContext };
|
||||
context.HttpContext = httpContext;
|
||||
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
var segment = new UrlSegment();
|
||||
var results = segment.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("/foo/bar", results);
|
||||
Assert.Equal(expectedResult, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue