Feedback from David and API Review/ Tests
This commit is contained in:
parent
0cb7445921
commit
f3b4658c2c
|
|
@ -1,10 +1,3 @@
|
|||
# Ensure Https
|
||||
RewriteCond %{HTTPS} off
|
||||
RewriteRule ^(.*)$ https://www.example.com$1 [L]
|
||||
|
||||
# Rewrite path with additional sub directory
|
||||
RewriteRule ^(.*)$ /foo$1
|
||||
|
||||
# Forbid a certain url from being accessed
|
||||
RewriteRule /bar - [F]
|
||||
RewriteRule /bar/ - [F]
|
||||
# Rewrite path with additional sub directory
|
||||
RewriteCond %{QUERY_STRING} id=20
|
||||
RewriteRule ^(.*)$ - [G]
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Builder;
|
|||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
|
||||
namespace RewriteSample
|
||||
{
|
||||
|
|
@ -26,16 +25,11 @@ namespace RewriteSample
|
|||
// (ex StringReplace) that are easy to implement in code, they can do so by calling
|
||||
// AddFunctionalRule(Func);
|
||||
// TODO make this startup do something useful.
|
||||
|
||||
app.UseRewriter(new RewriteOptions()
|
||||
.Rewrite(@"foo/(\d+)", "foo?id={R:1}")
|
||||
.ImportFromUrlRewrite(hostingEnv, "UrlRewrite.xml")
|
||||
.ImportFromModRewrite(hostingEnv, "Rewrite.txt")
|
||||
.RedirectToHttps(StatusCodes.Status307TemporaryRedirect)
|
||||
.RewriteRule("/foo/(.*)/bar", "{R:1}/bar")
|
||||
.AddRule(ctx =>
|
||||
{
|
||||
ctx.HttpContext.Request.Path = "/index";
|
||||
return RuleResult.Continue;
|
||||
}));
|
||||
.ImportFromModRewrite(hostingEnv, "Rewrite.txt"));
|
||||
|
||||
app.Run(context => context.Response.WriteAsync($"Rewritten Url: {context.Request.Path + context.Request.QueryString}"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<rewrite>
|
||||
<rules>
|
||||
<rule name="Example" stopProcessing="true">
|
||||
<match url="(.*)" />
|
||||
<action type="Rewrite" url="http://example.com/{R:1}" />
|
||||
<rule name="" stopProcessing="true">
|
||||
<match url="foo/bar" />
|
||||
<action type="Redirect" redirectType="Found" url="foo/" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.CodeRules;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
/// <summary>
|
||||
/// The builder to a list of rules for <see cref="RewriteOptions"/> and <see cref="RewriteMiddleware"/>
|
||||
/// </summary>
|
||||
public static class CodeRewriteExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a rule to the current rules.
|
||||
/// </summary>
|
||||
/// <param name="options">The UrlRewrite options.</param>
|
||||
/// <param name="rule">A rule to be added to the current rules.</param>
|
||||
public static RewriteOptions AddRule(this RewriteOptions options, Rule rule)
|
||||
{
|
||||
options.Rules.Add(rule);
|
||||
return options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a list of rules to the current rules.
|
||||
/// </summary>
|
||||
/// <param name="options">The UrlRewrite options.</param>
|
||||
/// <param name="rules">A list of rules.</param>
|
||||
public static RewriteOptions AddRules(this RewriteOptions options, List<Rule> rules)
|
||||
{
|
||||
options.Rules.AddRange(rules);
|
||||
return options;
|
||||
}
|
||||
|
||||
public static RewriteOptions RewriteRule(this RewriteOptions options, string regex, string onMatch)
|
||||
{
|
||||
return RewriteRule(options, regex, onMatch, stopProcessing: false);
|
||||
}
|
||||
|
||||
public static RewriteOptions RewriteRule(this RewriteOptions options, string regex, string onMatch, bool stopProcessing)
|
||||
{
|
||||
var builder = new UrlRewriteRuleBuilder();
|
||||
var pattern = new InputParser().ParseInputString(onMatch);
|
||||
|
||||
builder.AddUrlMatch(regex);
|
||||
builder.AddUrlAction(pattern, actionType: ActionType.Rewrite, stopProcessing: stopProcessing);
|
||||
options.Rules.Add(builder.Build());
|
||||
return options;
|
||||
}
|
||||
|
||||
public static RewriteOptions RedirectRule(this RewriteOptions options, string regex, string onMatch, int statusCode)
|
||||
{
|
||||
return RedirectRule(options, regex, onMatch, statusCode, stopProcessing: false);
|
||||
}
|
||||
|
||||
public static RewriteOptions RedirectRule(this RewriteOptions options, string regex, string onMatch, int statusCode, bool stopProcessing)
|
||||
{
|
||||
var builder = new UrlRewriteRuleBuilder();
|
||||
var pattern = new InputParser().ParseInputString(onMatch);
|
||||
|
||||
builder.AddUrlMatch(regex);
|
||||
builder.AddUrlAction(pattern, actionType: ActionType.Redirect, stopProcessing: stopProcessing);
|
||||
options.Rules.Add(builder.Build());
|
||||
return options;
|
||||
}
|
||||
|
||||
public static RewriteOptions RedirectToHttps(this RewriteOptions options, int statusCode)
|
||||
{
|
||||
return RedirectToHttps(options, statusCode, null);
|
||||
}
|
||||
|
||||
public static RewriteOptions RedirectToHttps(this RewriteOptions options, int statusCode, int? sslPort)
|
||||
{
|
||||
options.Rules.Add(new RedirectToHttpsRule { StatusCode = statusCode, SSLPort = sslPort });
|
||||
return options;
|
||||
}
|
||||
|
||||
public static RewriteOptions RewriteToHttps(this RewriteOptions options)
|
||||
{
|
||||
return RewriteToHttps(options, sslPort: null, stopProcessing: false);
|
||||
}
|
||||
|
||||
public static RewriteOptions RewriteToHttps(this RewriteOptions options, int? sslPort)
|
||||
{
|
||||
return RewriteToHttps(options, sslPort, stopProcessing: false);
|
||||
}
|
||||
|
||||
public static RewriteOptions RewriteToHttps(this RewriteOptions options, int? sslPort, bool stopProcessing)
|
||||
{
|
||||
options.Rules.Add(new RewriteToHttpsRule {SSLPort = sslPort, StopProcessing = stopProcessing });
|
||||
return options;
|
||||
}
|
||||
|
||||
public static RewriteOptions AddRule(this RewriteOptions options, Func<RewriteContext, RuleResult> rule)
|
||||
{
|
||||
options.Rules.Add(new FunctionalRule { OnApplyRule = rule});
|
||||
return options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,9 +5,14 @@ using System;
|
|||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.CodeRules
|
||||
{
|
||||
public class FunctionalRule : Rule
|
||||
public class DelegateRule : Rule
|
||||
{
|
||||
public Func<RewriteContext, RuleResult> OnApplyRule { get; set; }
|
||||
public override RuleResult ApplyRule(RewriteContext context) => OnApplyRule(context);
|
||||
private readonly Func<RewriteContext, RuleResult> _onApplyRule;
|
||||
|
||||
public DelegateRule(Func<RewriteContext, RuleResult> onApplyRule)
|
||||
{
|
||||
_onApplyRule = onApplyRule;
|
||||
}
|
||||
public override RuleResult ApplyRule(RewriteContext context) => _onApplyRule(context);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.CodeRules
|
||||
{
|
||||
public class RewriteToHttpsRule : Rule
|
||||
{
|
||||
public bool StopProcessing { get; set; }
|
||||
public int? SSLPort { get; set; }
|
||||
|
||||
public override RuleResult ApplyRule(RewriteContext context)
|
||||
{
|
||||
if (!context.HttpContext.Request.IsHttps)
|
||||
{
|
||||
var host = context.HttpContext.Request.Host;
|
||||
if (SSLPort.HasValue && SSLPort.Value > 0)
|
||||
{
|
||||
// a specific SSL port is specified
|
||||
host = new HostString(host.Host, SSLPort.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// clear the port
|
||||
host = new HostString(host.Host);
|
||||
}
|
||||
|
||||
context.HttpContext.Request.Scheme = "https";
|
||||
context.HttpContext.Request.Host = host;
|
||||
return StopProcessing ? RuleResult.StopRules: RuleResult.Continue;
|
||||
}
|
||||
return RuleResult.Continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,15 +5,14 @@ using System.Collections.Generic;
|
|||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||
{
|
||||
public class Conditions
|
||||
public static class ConditionHelper
|
||||
{
|
||||
public List<Condition> ConditionList { get; set; } = new List<Condition>();
|
||||
|
||||
public MatchResults Evaluate(RewriteContext context, MatchResults ruleMatch)
|
||||
public static MatchResults Evaluate(IEnumerable<Condition> conditions, RewriteContext context, MatchResults ruleMatch)
|
||||
{
|
||||
MatchResults prevCond = null;
|
||||
var orSucceeded = false;
|
||||
foreach (var condition in ConditionList)
|
||||
foreach (var condition in conditions)
|
||||
{
|
||||
if (orSucceeded && condition.OrNext)
|
||||
{
|
||||
|
|
@ -30,7 +29,6 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
|||
if (condition.OrNext)
|
||||
{
|
||||
orSucceeded = prevCond.Success;
|
||||
continue;
|
||||
}
|
||||
else if (!prevCond.Success)
|
||||
{
|
||||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
/// <returns>A new parsed condition.</returns>
|
||||
public ParsedModRewriteInput ParseActionCondition(string condition)
|
||||
{
|
||||
if (condition == null)
|
||||
if (condition == null)
|
||||
{
|
||||
condition = string.Empty;
|
||||
}
|
||||
|
|
@ -120,7 +120,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
}
|
||||
|
||||
// Capture the rest of the string guarantee validity.
|
||||
results.Operand = condition.Substring(context.GetIndex());
|
||||
results.Operand = condition.Substring(context.GetIndex());
|
||||
if (IsValidActionCondition(results))
|
||||
{
|
||||
return results;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
{
|
||||
public class FileParser
|
||||
{
|
||||
public List<Rule> Parse(TextReader input)
|
||||
public IList<Rule> Parse(TextReader input)
|
||||
{
|
||||
string line;
|
||||
var rules = new List<Rule>();
|
||||
|
|
@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
builder.AddAction(pattern, flags);
|
||||
rules.Add(builder.Build());
|
||||
builder = new RuleBuilder();
|
||||
}
|
||||
}
|
||||
catch (FormatException formatException)
|
||||
{
|
||||
throw new FormatException(Resources.FormatError_ModRewriteGeneralParseError(lineNum), formatException);
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
public bool EscapeBackReferences { get; }
|
||||
|
||||
public ModRewriteRedirectAction(
|
||||
int statusCode,
|
||||
Pattern pattern,
|
||||
bool queryStringAppend,
|
||||
bool queryStringDelete,
|
||||
int statusCode,
|
||||
Pattern pattern,
|
||||
bool queryStringAppend,
|
||||
bool queryStringDelete,
|
||||
bool escapeBackReferences)
|
||||
{
|
||||
StatusCode = statusCode;
|
||||
|
|
@ -42,19 +42,11 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
// always add to location header.
|
||||
// TODO check for false positives
|
||||
var split = pattern.IndexOf('?');
|
||||
if (split >= 0)
|
||||
if (split >= 0 && QueryStringAppend)
|
||||
{
|
||||
QueryString query;
|
||||
if (QueryStringAppend)
|
||||
{
|
||||
query = context.HttpContext.Request.QueryString.Add(
|
||||
QueryString.FromUriComponent(
|
||||
pattern.Substring(split)));
|
||||
}
|
||||
else
|
||||
{
|
||||
query = QueryString.FromUriComponent(pattern.Substring(split));
|
||||
}
|
||||
var query = context.HttpContext.Request.QueryString.Add(
|
||||
QueryString.FromUriComponent(
|
||||
pattern.Substring(split)));
|
||||
|
||||
// not using the response.redirect here because status codes may be 301, 302, 307, 308
|
||||
context.HttpContext.Response.Headers[HeaderNames.Location] = pattern.Substring(0, split) + query;
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
public bool EscapeBackReferences { get; }
|
||||
|
||||
public ModRewriteRewriteAction(
|
||||
RuleResult result,
|
||||
Pattern pattern,
|
||||
RuleResult result,
|
||||
Pattern pattern,
|
||||
bool queryStringAppend,
|
||||
bool queryStringDelete,
|
||||
bool escapeBackReferences)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
{
|
||||
public class RuleBuilder
|
||||
{
|
||||
private Conditions _conditions;
|
||||
private IList<Condition> _conditions;
|
||||
private UrlAction _action;
|
||||
private UrlMatch _match;
|
||||
private List<PreAction> _preActions;
|
||||
|
|
@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
{
|
||||
if (_conditions == null)
|
||||
{
|
||||
_conditions = new Conditions();
|
||||
_conditions = new List<Condition>();
|
||||
}
|
||||
|
||||
var condition = new Condition();
|
||||
|
|
@ -147,7 +147,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
}
|
||||
break;
|
||||
}
|
||||
_conditions.ConditionList.Add(condition);
|
||||
_conditions.Add(condition);
|
||||
}
|
||||
|
||||
public void AddMatch(
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
}
|
||||
else
|
||||
{
|
||||
return new ParsedModRewriteInput { Invert = false, Operand = regex};
|
||||
return new ParsedModRewriteInput { Invert = false, Operand = regex };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,7 +106,6 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
case "HTTP2":
|
||||
throw new NotImplementedException("Http2 server variable is not supported");
|
||||
case "IS_SUBREQ":
|
||||
// TODO maybe can do this? context.Request.HttpContext ?
|
||||
throw new NotImplementedException("Is-Subrequest server variable is not supported");
|
||||
case "REQUEST_FILENAME":
|
||||
return new RequestFileNameSegment();
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
var ruleVariable = context.Capture();
|
||||
context.Back();
|
||||
var parsedIndex = int.Parse(ruleVariable);
|
||||
|
||||
|
||||
results.Add(new RuleMatchSegment(parsedIndex));
|
||||
}
|
||||
else
|
||||
|
|
@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
/// <param name="context">The ParserContext</param>
|
||||
/// <param name="results">The List of results which the new condition parameter will be added.</param>
|
||||
/// <returns>true </returns>
|
||||
private static void ParseConditionParameter(ParserContext context, List<PatternSegment> results)
|
||||
private static void ParseConditionParameter(ParserContext context, IList<PatternSegment> results)
|
||||
{
|
||||
// Parse { }
|
||||
if (context.Current == OpenBrace)
|
||||
|
|
@ -146,7 +146,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
/// <param name="context"></param>
|
||||
/// <param name="results"></param>
|
||||
/// <returns></returns>
|
||||
private static void ParseLiteral(ParserContext context, List<PatternSegment> results)
|
||||
private static void ParseLiteral(ParserContext context, IList<PatternSegment> results)
|
||||
{
|
||||
context.Mark();
|
||||
string literal;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
/// </summary>
|
||||
/// <param name="rule">The rule to tokenize.</param>
|
||||
/// <returns>A list of tokens.</returns>
|
||||
public List<string> Tokenize(string rule)
|
||||
public IList<string> Tokenize(string rule)
|
||||
{
|
||||
// TODO make list of strings a reference to the original rule? (run into problems with escaped spaces).
|
||||
// TODO handle "s and probably replace \ character with no slash.
|
||||
|
|
|
|||
|
|
@ -2,18 +2,18 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||
{
|
||||
public class ModRewriteRule : Rule
|
||||
{
|
||||
public UrlMatch InitialMatch { get; set; }
|
||||
public Conditions Conditions { get; set; }
|
||||
public UrlAction Action { get; set; }
|
||||
public List<PreAction> PreActions { get; set; }
|
||||
public UrlMatch InitialMatch { get; }
|
||||
public IList<Condition> Conditions { get; }
|
||||
public UrlAction Action { get; }
|
||||
public IList<PreAction> PreActions { get; }
|
||||
|
||||
public ModRewriteRule(UrlMatch initialMatch, Conditions conditions, UrlAction urlAction, List<PreAction> preActions)
|
||||
public ModRewriteRule(UrlMatch initialMatch, IList<Condition> conditions, UrlAction urlAction, IList<PreAction> preActions)
|
||||
{
|
||||
Conditions = conditions;
|
||||
InitialMatch = initialMatch;
|
||||
|
|
@ -28,21 +28,24 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
|||
|
||||
if (!initMatchRes.Success)
|
||||
{
|
||||
context.Logger?.ModRewriteDidNotMatchRule();
|
||||
return RuleResult.Continue;
|
||||
}
|
||||
|
||||
MatchResults condMatchRes = null;
|
||||
if (Conditions != null)
|
||||
{
|
||||
condMatchRes = Conditions.Evaluate(context, initMatchRes);
|
||||
condMatchRes = ConditionHelper.Evaluate(Conditions, context, initMatchRes);
|
||||
if (!condMatchRes.Success)
|
||||
{
|
||||
context.Logger?.ModRewriteDidNotMatchRule();
|
||||
return RuleResult.Continue;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, we know our rule passed, first apply pre conditions,
|
||||
// which can modify things like the cookie or env, and then apply the action
|
||||
context.Logger?.ModRewriteMatchedRule();
|
||||
foreach (var preAction in PreActions)
|
||||
{
|
||||
preAction.ApplyAction(context.HttpContext, initMatchRes, condMatchRes);
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||
{
|
||||
public abstract class PatternSegment
|
||||
{
|
||||
// Match from prevRule, Match from prevCond
|
||||
public abstract string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
|||
|
||||
public DateTimeSegment(string segment)
|
||||
{
|
||||
switch(segment)
|
||||
switch (segment)
|
||||
{
|
||||
case "TIME_YEAR":
|
||||
_portion = DateTimePortion.Year;
|
||||
|
|
@ -24,28 +24,29 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
|||
_portion = DateTimePortion.Day;
|
||||
break;
|
||||
case "TIME_HOUR":
|
||||
_portion = DateTimePortion.Day;
|
||||
_portion = DateTimePortion.Hour;
|
||||
break;
|
||||
case "TIME_MIN":
|
||||
_portion = DateTimePortion.Day;
|
||||
_portion = DateTimePortion.Minute;
|
||||
break;
|
||||
case "TIME_SEC":
|
||||
_portion = DateTimePortion.Day;
|
||||
_portion = DateTimePortion.Second;
|
||||
break;
|
||||
case "TIME_WDAY":
|
||||
_portion = DateTimePortion.Day;
|
||||
_portion = DateTimePortion.DayOfWeek;
|
||||
break;
|
||||
case "TIME":
|
||||
_portion = DateTimePortion.Day;
|
||||
_portion = DateTimePortion.Time;
|
||||
break;
|
||||
default:
|
||||
throw new FormatException("Unsupported segment: " + segment);
|
||||
throw new FormatException($"Unsupported segment: '{segment}'");
|
||||
}
|
||||
}
|
||||
|
||||
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||
{
|
||||
switch (_portion) {
|
||||
switch (_portion)
|
||||
{
|
||||
case DateTimePortion.Year:
|
||||
return DateTimeOffset.UtcNow.Year.ToString(CultureInfo.InvariantCulture);
|
||||
case DateTimePortion.Month:
|
||||
|
|
@ -67,7 +68,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
|||
}
|
||||
}
|
||||
|
||||
private enum DateTimePortion {
|
||||
private enum DateTimePortion
|
||||
{
|
||||
Year,
|
||||
Month,
|
||||
Day,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
|||
public class HeaderSegment : PatternSegment
|
||||
{
|
||||
private readonly string _header;
|
||||
|
||||
|
||||
public HeaderSegment(string header)
|
||||
{
|
||||
_header = header;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
|||
public class UrlEncodeSegment : PatternSegment
|
||||
{
|
||||
private readonly Pattern _pattern;
|
||||
|
||||
|
||||
public UrlEncodeSegment(Pattern pattern)
|
||||
{
|
||||
_pattern = pattern;
|
||||
|
|
@ -17,10 +17,14 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
|||
|
||||
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||
{
|
||||
var tempBuilder = context.Builder;
|
||||
var oldBuilder = context.Builder;
|
||||
// PERF
|
||||
// Because we need to be able to evaluate multiple nested patterns,
|
||||
// we provided a new string builder and evaluate the new pattern,
|
||||
// and restore it after evaluation.
|
||||
context.Builder = new StringBuilder(64);
|
||||
var pattern = _pattern.Evaluate(context, ruleMatch, condMatch);
|
||||
context.Builder = tempBuilder;
|
||||
context.Builder = oldBuilder;
|
||||
return UrlEncoder.Default.Encode(pattern);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PreActions
|
|||
public override void ApplyAction(HttpContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||
{
|
||||
// modify the cookies
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
|||
{
|
||||
public abstract class UrlAction
|
||||
{
|
||||
public Pattern Url { get; set; }
|
||||
protected Pattern Url { get; set; }
|
||||
public abstract RuleResult ApplyAction(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
|
|
@ -9,25 +10,33 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
|
|||
public class RedirectAction : UrlAction
|
||||
{
|
||||
public int StatusCode { get; }
|
||||
public RedirectAction(int statusCode, Pattern pattern)
|
||||
public bool AppendQueryString { get; }
|
||||
|
||||
public RedirectAction(int statusCode, Pattern pattern, bool appendQueryString)
|
||||
{
|
||||
StatusCode = statusCode;
|
||||
Url = pattern;
|
||||
AppendQueryString = appendQueryString;
|
||||
}
|
||||
|
||||
public override RuleResult ApplyAction(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||
{
|
||||
|
||||
var pattern = Url.Evaluate(context, ruleMatch, condMatch);
|
||||
context.HttpContext.Response.StatusCode = StatusCode;
|
||||
|
||||
// TODO IIS guarantees that there will be a leading slash
|
||||
if (pattern.IndexOf("://", StringComparison.Ordinal) == -1 && !pattern.StartsWith("/"))
|
||||
{
|
||||
pattern = '/' + pattern;
|
||||
}
|
||||
|
||||
// url can either contain the full url or the path and query
|
||||
// always add to location header.
|
||||
// TODO check for false positives
|
||||
var split = pattern.IndexOf('?');
|
||||
if (split >= 0)
|
||||
if (split >= 0 && AppendQueryString)
|
||||
{
|
||||
var query = context.HttpContext.Request.QueryString.Add(
|
||||
var query = context.HttpContext.Request.QueryString.Add(
|
||||
QueryString.FromUriComponent(
|
||||
pattern.Substring(split)));
|
||||
// not using the HttpContext.Response.redirect here because status codes may be 301, 302, 307, 308
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
|
||||
{
|
||||
public class RedirectClearQueryAction : UrlAction
|
||||
{
|
||||
public int StatusCode { get; }
|
||||
public RedirectClearQueryAction(int statusCode, Pattern pattern)
|
||||
{
|
||||
StatusCode = statusCode;
|
||||
Url = pattern;
|
||||
}
|
||||
|
||||
public override RuleResult ApplyAction(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||
{
|
||||
var pattern = Url.Evaluate(context, ruleMatch, condMatch);
|
||||
context.HttpContext.Response.StatusCode = StatusCode;
|
||||
|
||||
// we are clearing the query, so just put the pattern in the location header
|
||||
context.HttpContext.Response.Headers[HeaderNames.Location] = pattern;
|
||||
return RuleResult.ResponseComplete;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,10 +10,10 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
|
|||
public class RewriteAction : UrlAction
|
||||
{
|
||||
private readonly string ForwardSlash = "/";
|
||||
public RuleTerminiation Result { get; }
|
||||
public RuleTermination Result { get; }
|
||||
public bool ClearQuery { get; }
|
||||
|
||||
public RewriteAction(RuleTerminiation result, Pattern pattern, bool clearQuery)
|
||||
public RewriteAction(RuleTermination result, Pattern pattern, bool clearQuery)
|
||||
{
|
||||
Result = result;
|
||||
Url = pattern;
|
||||
|
|
@ -28,8 +28,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
|
|||
{
|
||||
context.HttpContext.Request.QueryString = QueryString.Empty;
|
||||
}
|
||||
// TODO PERF, substrings, object creation, etc.
|
||||
if (pattern.IndexOf("://") >= 0)
|
||||
|
||||
if (pattern.IndexOf("://", StringComparison.Ordinal) >= 0)
|
||||
{
|
||||
string scheme;
|
||||
HostString host;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
|
|||
|
||||
public override MatchResults Evaluate(string input, RewriteContext context)
|
||||
{
|
||||
var fileInfo = context.FileProvider.GetFileInfo(input);
|
||||
var fileInfo = context.StaticFileProvider.GetFileInfo(input);
|
||||
return fileInfo.Exists && fileInfo.Length > 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
|
|||
public class IsDirectoryMatch : UrlMatch
|
||||
{
|
||||
public IsDirectoryMatch(bool negate)
|
||||
{
|
||||
{
|
||||
Negate = negate;
|
||||
}
|
||||
|
||||
public override MatchResults Evaluate(string pattern, RewriteContext context)
|
||||
{
|
||||
var res = context.FileProvider.GetFileInfo(pattern).IsDirectory;
|
||||
var res = context.StaticFileProvider.GetFileInfo(pattern).IsDirectory;
|
||||
return new MatchResults { Success = (res != Negate) };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
|
||||
{
|
||||
public class IsFileMatch : UrlMatch
|
||||
{
|
||||
{
|
||||
public IsFileMatch(bool negate)
|
||||
{
|
||||
Negate = negate;
|
||||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
|
|||
|
||||
public override MatchResults Evaluate(string pattern, RewriteContext context)
|
||||
{
|
||||
var res = context.FileProvider.GetFileInfo(pattern).Exists;
|
||||
var res = context.StaticFileProvider.GetFileInfo(pattern).Exists;
|
||||
return new MatchResults { Success = (res != Negate) };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches
|
|||
public override MatchResults Evaluate(string pattern, RewriteContext context)
|
||||
{
|
||||
var res = _match.Match(pattern);
|
||||
return new MatchResults { BackReference = res.Groups, Success = (res.Success != Negate)};
|
||||
return new MatchResults { BackReference = res.Groups, Success = (res.Success != Negate) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
||||
|
|
@ -60,7 +59,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
|||
return new Pattern(results);
|
||||
}
|
||||
|
||||
private static void ParseParameter(ParserContext context, List<PatternSegment> results)
|
||||
private static void ParseParameter(ParserContext context, IList<PatternSegment> results)
|
||||
{
|
||||
context.Mark();
|
||||
// Four main cases:
|
||||
|
|
@ -82,7 +81,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
|||
else if (context.Current == Colon)
|
||||
{
|
||||
parameter = context.Capture();
|
||||
|
||||
|
||||
// Only 5 strings to expect here. Case sensitive.
|
||||
switch (parameter)
|
||||
{
|
||||
|
|
@ -165,7 +164,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
|||
return index;
|
||||
}
|
||||
|
||||
private static void ParseLiteral(ParserContext context, List<PatternSegment> results)
|
||||
private static void ParseLiteral(ParserContext context, IList<PatternSegment> results)
|
||||
{
|
||||
context.Mark();
|
||||
string literal;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
|
|
@ -12,7 +11,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
|||
{
|
||||
public static PatternSegment FindServerVariable(string serverVariable)
|
||||
{
|
||||
switch(serverVariable)
|
||||
switch (serverVariable)
|
||||
{
|
||||
// TODO Add all server variables here.
|
||||
case "ALL_RAW":
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ using System.Xml.Linq;
|
|||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
||||
{
|
||||
public class FileParser
|
||||
public class UrlRewriteFileParser
|
||||
{
|
||||
private readonly InputParser _inputParser = new InputParser();
|
||||
|
||||
public List<UrlRewriteRule> Parse(TextReader reader)
|
||||
public IList<UrlRewriteRule> Parse(TextReader reader)
|
||||
{
|
||||
var xmlDoc = XDocument.Load(reader, LoadOptions.SetLineInfo);
|
||||
var xmlRoot = xmlDoc.Descendants(RewriteTags.Rewrite).FirstOrDefault();
|
||||
|
|
@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
|||
return null;
|
||||
}
|
||||
|
||||
private void ParseRules(XElement rules, List<UrlRewriteRule> result)
|
||||
private void ParseRules(XElement rules, IList<UrlRewriteRule> result)
|
||||
{
|
||||
if (rules == null)
|
||||
{
|
||||
|
|
@ -13,12 +13,12 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
|||
public class UrlRewriteRuleBuilder
|
||||
{
|
||||
private readonly TimeSpan RegexTimeout = TimeSpan.FromMilliseconds(1);
|
||||
|
||||
|
||||
public string Name { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
private UrlMatch _initialMatch;
|
||||
private Conditions _conditions;
|
||||
private IList<Condition> _conditions;
|
||||
private UrlAction _action;
|
||||
private bool _matchAny;
|
||||
|
||||
|
|
@ -28,40 +28,28 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
|||
{
|
||||
throw new InvalidOperationException("Cannot create UrlRewriteRule without action and match");
|
||||
}
|
||||
var rule = new UrlRewriteRule();
|
||||
rule.Action = _action;
|
||||
rule.Conditions = _conditions;
|
||||
rule.InitialMatch = _initialMatch;
|
||||
rule.Name = Name;
|
||||
return rule;
|
||||
|
||||
return new UrlRewriteRule(Name, _initialMatch, _conditions, _action);
|
||||
}
|
||||
|
||||
public void AddUrlAction(Pattern url, ActionType actionType = ActionType.None, bool appendQueryString = true, bool stopProcessing = false, int statusCode = StatusCodes.Status301MovedPermanently)
|
||||
|
||||
public void AddUrlAction(
|
||||
Pattern url,
|
||||
ActionType actionType = ActionType.None,
|
||||
bool appendQueryString = true,
|
||||
bool stopProcessing = false,
|
||||
int statusCode = StatusCodes.Status301MovedPermanently)
|
||||
{
|
||||
switch (actionType)
|
||||
{
|
||||
case ActionType.None:
|
||||
_action = new VoidAction(stopProcessing ? RuleResult.StopRules : RuleResult.Continue);
|
||||
_action = new VoidAction(stopProcessing ? RuleResult.StopRules : RuleResult.Continue);
|
||||
break;
|
||||
case ActionType.Rewrite:
|
||||
if (appendQueryString)
|
||||
{
|
||||
_action = new RewriteAction(stopProcessing ? RuleTerminiation.StopRules : RuleTerminiation.Continue, url, clearQuery: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_action = new RewriteAction(stopProcessing ? RuleTerminiation.StopRules : RuleTerminiation.Continue, url, clearQuery: true);
|
||||
}
|
||||
_action = new RewriteAction(stopProcessing ? RuleTermination.StopRules : RuleTermination.Continue,
|
||||
url, clearQuery: !appendQueryString);
|
||||
break;
|
||||
case ActionType.Redirect:
|
||||
if (appendQueryString)
|
||||
{
|
||||
_action = new RedirectAction(statusCode, url);
|
||||
}
|
||||
else
|
||||
{
|
||||
_action = new RedirectClearQueryAction(statusCode, url);
|
||||
}
|
||||
_action = new RedirectAction(statusCode, url, appendQueryString);
|
||||
break;
|
||||
case ActionType.AbortRequest:
|
||||
throw new NotImplementedException("Abort Requests are not supported");
|
||||
|
|
@ -85,14 +73,14 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
|||
else
|
||||
{
|
||||
var regex = new Regex(input, RegexOptions.CultureInvariant | RegexOptions.Compiled, RegexTimeout);
|
||||
_initialMatch = new RegexMatch(regex, negate);
|
||||
_initialMatch = new RegexMatch(regex, negate);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PatternSyntax.WildCard:
|
||||
throw new NotImplementedException("Wildcard syntax is not supported");
|
||||
case PatternSyntax.ExactMatch:
|
||||
_initialMatch = new ExactMatch(ignoreCase, input, negate);
|
||||
_initialMatch = new ExactMatch(ignoreCase, input, negate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -118,27 +106,23 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
|||
throw new FormatException("Match does not have an associated pattern attribute in condition");
|
||||
}
|
||||
|
||||
Regex regex = null;
|
||||
if (ignoreCase)
|
||||
{
|
||||
regex = new Regex(pattern, RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
regex = new Regex(pattern, RegexOptions.CultureInvariant | RegexOptions.Compiled, RegexTimeout);
|
||||
}
|
||||
|
||||
_conditions.ConditionList.Add(new Condition { Input = input, Match = new RegexMatch(regex, negate), OrNext = _matchAny});
|
||||
var regex = new Regex(
|
||||
pattern,
|
||||
ignoreCase ? RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase :
|
||||
RegexOptions.CultureInvariant | RegexOptions.Compiled,
|
||||
RegexTimeout);
|
||||
|
||||
_conditions.Add(new Condition { Input = input, Match = new RegexMatch(regex, negate), OrNext = _matchAny });
|
||||
break;
|
||||
}
|
||||
case MatchType.IsDirectory:
|
||||
{
|
||||
_conditions.ConditionList.Add(new Condition { Input = input, Match = new IsDirectoryMatch(negate), OrNext = _matchAny });
|
||||
_conditions.Add(new Condition { Input = input, Match = new IsDirectoryMatch(negate), OrNext = _matchAny });
|
||||
break;
|
||||
}
|
||||
case MatchType.IsFile:
|
||||
{
|
||||
_conditions.ConditionList.Add(new Condition { Input = input, Match = new IsFileMatch(negate), OrNext = _matchAny });
|
||||
_conditions.Add(new Condition { Input = input, Match = new IsFileMatch(negate), OrNext = _matchAny });
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -153,7 +137,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
|||
{
|
||||
throw new FormatException("Match does not have an associated pattern attribute in condition");
|
||||
}
|
||||
_conditions.ConditionList.Add(new Condition { Input = input, Match = new ExactMatch(ignoreCase, pattern, negate), OrNext = _matchAny });
|
||||
_conditions.Add(new Condition { Input = input, Match = new ExactMatch(ignoreCase, pattern, negate), OrNext = _matchAny });
|
||||
break;
|
||||
default:
|
||||
throw new FormatException("Unrecognized pattern syntax");
|
||||
|
|
@ -162,10 +146,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
|||
|
||||
public void AddUrlConditions(LogicalGrouping logicalGrouping, bool trackingAllCaptures)
|
||||
{
|
||||
var conditions = new Conditions();
|
||||
conditions.ConditionList = new List<Condition>();
|
||||
_conditions = new List<Condition>();
|
||||
_matchAny = logicalGrouping == LogicalGrouping.MatchAny;
|
||||
_conditions = conditions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,34 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||
{
|
||||
public class UrlRewriteRule : Rule
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public bool Enabled { get; set; } = true;
|
||||
public UrlMatch InitialMatch { get; set; }
|
||||
public Conditions Conditions { get; set; }
|
||||
public UrlAction Action { get; set; }
|
||||
public string Name { get; }
|
||||
public UrlMatch InitialMatch { get; }
|
||||
public IList<Condition> Conditions { get; }
|
||||
public UrlAction Action { get; }
|
||||
|
||||
public UrlRewriteRule(string name,
|
||||
UrlMatch initialMatch,
|
||||
IList<Condition> conditions,
|
||||
UrlAction action)
|
||||
{
|
||||
Name = name;
|
||||
InitialMatch = initialMatch;
|
||||
Conditions = conditions;
|
||||
Action = action;
|
||||
}
|
||||
|
||||
public override RuleResult ApplyRule(RewriteContext context)
|
||||
{
|
||||
if (!Enabled)
|
||||
{
|
||||
return RuleResult.Continue;
|
||||
}
|
||||
|
||||
// Due to the path string always having a leading slash,
|
||||
// remove it from the path before regex comparison
|
||||
// TODO may need to check if there is a leading slash and remove conditionally
|
||||
var path = context.HttpContext.Request.Path;
|
||||
MatchResults initMatchResults;
|
||||
if (path == PathString.Empty)
|
||||
|
|
@ -36,19 +42,22 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
|||
|
||||
if (!initMatchResults.Success)
|
||||
{
|
||||
context.Logger?.UrlRewriteDidNotMatchRule(Name);
|
||||
return RuleResult.Continue;
|
||||
}
|
||||
|
||||
MatchResults condMatchRes = null;
|
||||
if (Conditions != null)
|
||||
{
|
||||
condMatchRes = Conditions.Evaluate(context, initMatchResults);
|
||||
condMatchRes = ConditionHelper.Evaluate(Conditions, context, initMatchResults);
|
||||
if (!condMatchRes.Success)
|
||||
{
|
||||
context.Logger?.UrlRewriteDidNotMatchRule(Name);
|
||||
return RuleResult.Continue;
|
||||
}
|
||||
}
|
||||
|
||||
context.Logger?.UrlRewriteMatchedRule(Name);
|
||||
// at this point we know the rule passed, evaluate the replacement.
|
||||
return Action.ApplyAction(context, initMatchResults, condMatchRes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Logging
|
||||
{
|
||||
internal static class RewriteMiddlewareLoggingExtensions
|
||||
{
|
||||
private static readonly Action<ILogger, Exception> _requestContinueResults;
|
||||
private static readonly Action<ILogger, string, int, Exception> _requestResponseComplete;
|
||||
private static readonly Action<ILogger, Exception> _requestStopRules;
|
||||
private static readonly Action<ILogger, string, Exception> _urlRewriteDidNotMatchRule;
|
||||
private static readonly Action<ILogger, string, Exception> _urlRewriteMatchedRule;
|
||||
private static readonly Action<ILogger, Exception> _modRewriteDidNotMatchRule;
|
||||
private static readonly Action<ILogger, Exception> _modRewriteMatchedRule;
|
||||
|
||||
static RewriteMiddlewareLoggingExtensions()
|
||||
{
|
||||
_requestContinueResults = LoggerMessage.Define(
|
||||
LogLevel.Debug,
|
||||
1,
|
||||
"Request is continuing in applying rules.");
|
||||
_requestResponseComplete = LoggerMessage.Define<string, int>(
|
||||
LogLevel.Debug,
|
||||
2,
|
||||
"Request is done processing, Location header '{Location}' with status code '{StatusCode}'.");
|
||||
_requestStopRules = LoggerMessage.Define(
|
||||
LogLevel.Debug,
|
||||
3,
|
||||
"Request is done applying rules.");
|
||||
_urlRewriteDidNotMatchRule = LoggerMessage.Define<string>(
|
||||
LogLevel.Debug,
|
||||
4,
|
||||
"Request did not match current rule '{Name}'.");
|
||||
|
||||
_urlRewriteMatchedRule = LoggerMessage.Define<string>(
|
||||
LogLevel.Debug,
|
||||
5,
|
||||
"Request matched current UrlRewriteRule '{Name}'.");
|
||||
|
||||
_modRewriteDidNotMatchRule = LoggerMessage.Define(
|
||||
LogLevel.Debug,
|
||||
6,
|
||||
"Request matched current ModRewriteRule.");
|
||||
|
||||
_modRewriteMatchedRule = LoggerMessage.Define(
|
||||
LogLevel.Debug,
|
||||
7,
|
||||
"Request matched current ModRewriteRule.");
|
||||
}
|
||||
|
||||
public static void RewriteMiddlewareRequestContinueResults(this ILogger logger)
|
||||
{
|
||||
_requestContinueResults(logger, null);
|
||||
}
|
||||
|
||||
public static void RewriteMiddlewareRequestResponseComplete(this ILogger logger, string location, int statusCode)
|
||||
{
|
||||
_requestResponseComplete(logger, location, statusCode, null);
|
||||
}
|
||||
|
||||
public static void RewriteMiddlewareRequestStopRules(this ILogger logger)
|
||||
{
|
||||
_requestStopRules(logger, null);
|
||||
}
|
||||
|
||||
public static void UrlRewriteDidNotMatchRule(this ILogger logger, string name)
|
||||
{
|
||||
_urlRewriteDidNotMatchRule(logger, name, null);
|
||||
}
|
||||
|
||||
public static void UrlRewriteMatchedRule(this ILogger logger, string name)
|
||||
{
|
||||
_urlRewriteMatchedRule(logger, name, null);
|
||||
}
|
||||
|
||||
public static void ModRewriteDidNotMatchRule(this ILogger logger)
|
||||
{
|
||||
_modRewriteDidNotMatchRule(logger, null);
|
||||
}
|
||||
public static void ModRewriteMatchedRule(this ILogger logger)
|
||||
{
|
||||
_modRewriteMatchedRule(logger, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,24 +8,24 @@ using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite;
|
|||
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
public static class ModRewriteExtensions
|
||||
public static class ModRewriteOptionsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Imports rules from a mod_rewrite file and adds the rules to current rules.
|
||||
/// </summary>
|
||||
/// <param name="options">The UrlRewrite options.</param>
|
||||
/// <param name="hostingEnv"></param>
|
||||
/// <param name="options">The Rewrite options.</param>
|
||||
/// <param name="hostingEnvironment">The Hosting Environment</param>
|
||||
/// <param name="filePath">The path to the file containing mod_rewrite rules.</param>
|
||||
public static RewriteOptions ImportFromModRewrite(this RewriteOptions options, IHostingEnvironment hostingEnv, string filePath)
|
||||
public static RewriteOptions ImportFromModRewrite(this RewriteOptions options, IHostingEnvironment hostingEnvironment, string filePath)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
if (hostingEnv == null)
|
||||
if (hostingEnvironment == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostingEnv));
|
||||
throw new ArgumentNullException(nameof(hostingEnvironment));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(filePath))
|
||||
|
|
@ -33,18 +33,17 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
throw new ArgumentException(nameof(filePath));
|
||||
}
|
||||
|
||||
var path = Path.Combine(hostingEnv.ContentRootPath, filePath);
|
||||
var path = Path.Combine(hostingEnvironment.ContentRootPath, filePath);
|
||||
using (var stream = File.OpenRead(path))
|
||||
{
|
||||
options.Rules.AddRange(new FileParser().Parse(new StreamReader(stream)));
|
||||
};
|
||||
return options;
|
||||
return options.ImportFromModRewrite(new StreamReader(stream));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imports rules from a mod_rewrite file and adds the rules to current rules.
|
||||
/// </summary>
|
||||
/// <param name="options">The UrlRewrite options.</param>
|
||||
/// <param name="options">The Rewrite options.</param>
|
||||
/// <param name="reader">Text reader containing a stream of mod_rewrite rules.</param>
|
||||
public static RewriteOptions ImportFromModRewrite(this RewriteOptions options, TextReader reader)
|
||||
{
|
||||
|
|
@ -52,37 +51,19 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
|
||||
if (reader == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(reader));
|
||||
}
|
||||
options.Rules.AddRange(new FileParser().Parse(reader));
|
||||
var rules = new FileParser().Parse(reader);
|
||||
|
||||
foreach (var rule in rules)
|
||||
{
|
||||
options.Rules.Add(rule);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a mod_rewrite rule to the current rules.
|
||||
/// </summary>
|
||||
/// <param name="options">The UrlRewrite options.</param>
|
||||
/// <param name="rule">The literal string of a mod_rewrite rule:
|
||||
/// "RewriteRule Pattern Substitution [Flags]"</param>
|
||||
public static RewriteOptions AddModRewriteRule(this RewriteOptions options, string rule)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
if (rule == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(rule));
|
||||
}
|
||||
|
||||
var builder = new RuleBuilder();
|
||||
builder.AddRule(rule);
|
||||
options.Rules.Add(builder.Build());
|
||||
return options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,13 +9,13 @@ namespace Microsoft.AspNetCore.Builder
|
|||
/// <summary>
|
||||
/// Extension methods for the <see cref="RewriteMiddleware"/>
|
||||
/// </summary>
|
||||
public static class RewriteExtensions
|
||||
public static class RewriteBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if a given Url matches rules and conditions, and modifies the HttpContext on match.
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <param name="options">Options for urlrewrite.</param>
|
||||
/// <param name="options">Options for rewrite.</param>
|
||||
/// <returns></returns>
|
||||
public static IApplicationBuilder UseRewriter(this IApplicationBuilder app, RewriteOptions options)
|
||||
{
|
||||
|
|
@ -4,16 +4,19 @@
|
|||
using System.Text;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
/// <summary>
|
||||
/// The UrlRewrite Context contains the HttpContext of the request and the file provider to check conditions.
|
||||
/// The UrlRewrite Context contains the HttpContext of the request, the file provider, and the logger.
|
||||
/// There is also a shared string builder across the application of rules.
|
||||
/// </summary>
|
||||
public class RewriteContext
|
||||
{
|
||||
public HttpContext HttpContext { get; set; }
|
||||
public IFileProvider FileProvider { get; set; }
|
||||
public IFileProvider StaticFileProvider { get; set; }
|
||||
public ILogger Logger { get; set; }
|
||||
// PERF: share the same string builder per request
|
||||
internal StringBuilder Builder { get; set; } = new StringBuilder(64);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Logging;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
|
|
@ -20,14 +23,20 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
private readonly RequestDelegate _next;
|
||||
private readonly RewriteOptions _options;
|
||||
private readonly IFileProvider _fileProvider;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RewriteMiddleware"/>
|
||||
/// </summary>
|
||||
/// <param name="next">The delegate representing the next middleware in the request pipeline.</param>
|
||||
/// <param name="hostingEnv">The Hosting Environment.</param>
|
||||
/// <param name="hostingEnvironment">The Hosting Environment.</param>
|
||||
/// <param name="loggerFactory">The Logger Factory.</param>
|
||||
/// <param name="options">The middleware options, containing the rules to apply.</param>
|
||||
public RewriteMiddleware(RequestDelegate next, IHostingEnvironment hostingEnv, RewriteOptions options)
|
||||
public RewriteMiddleware(
|
||||
RequestDelegate next,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
ILoggerFactory loggerFactory,
|
||||
RewriteOptions options)
|
||||
{
|
||||
if (next == null)
|
||||
{
|
||||
|
|
@ -41,7 +50,8 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
|
||||
_next = next;
|
||||
_options = options;
|
||||
_fileProvider = _options.FileProvider ?? hostingEnv.WebRootFileProvider;
|
||||
_fileProvider = _options.StaticFileProvider ?? hostingEnvironment.WebRootFileProvider;
|
||||
_logger = loggerFactory.CreateLogger<RewriteMiddleware>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -55,19 +65,27 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
var urlContext = new RewriteContext { HttpContext = context, FileProvider = _fileProvider };
|
||||
var urlContext = new RewriteContext {
|
||||
HttpContext = context,
|
||||
StaticFileProvider = _fileProvider,
|
||||
Logger = _logger
|
||||
};
|
||||
|
||||
foreach (var rule in _options.Rules)
|
||||
{
|
||||
// Apply the rule
|
||||
var result = rule.ApplyRule(urlContext);
|
||||
switch (result.Result)
|
||||
{
|
||||
case RuleTerminiation.Continue:
|
||||
// Explicitly show that we continue executing rules
|
||||
case RuleTermination.Continue:
|
||||
_logger.RewriteMiddlewareRequestContinueResults();
|
||||
break;
|
||||
case RuleTerminiation.ResponseComplete:
|
||||
case RuleTermination.ResponseComplete:
|
||||
_logger.RewriteMiddlewareRequestResponseComplete(
|
||||
urlContext.HttpContext.Response.Headers[HeaderNames.Location],
|
||||
urlContext.HttpContext.Response.StatusCode);
|
||||
return CompletedTask;
|
||||
case RuleTerminiation.StopRules:
|
||||
case RuleTermination.StopRules:
|
||||
_logger.RewriteMiddlewareRequestStopRules();
|
||||
return _next(context);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException($"Invalid rule termination {result}");
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
|
|
@ -12,10 +11,8 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
/// </summary>
|
||||
public class RewriteOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The ordered list of rules to apply to the context.
|
||||
/// </summary>
|
||||
public List<Rule> Rules { get; set; } = new List<Rule>();
|
||||
public IFileProvider FileProvider { get; set; }
|
||||
// TODO doc comments
|
||||
public IList<Rule> Rules { get; } = new List<Rule>();
|
||||
public IFileProvider StaticFileProvider { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,135 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.CodeRules;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
/// <summary>
|
||||
/// The builder to a list of rules for <see cref="RewriteOptions"/> and <see cref="RewriteMiddleware"/>
|
||||
/// </summary>
|
||||
public static class RewriteOptionsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a rule to the current rules.
|
||||
/// </summary>
|
||||
/// <param name="options">The UrlRewrite options.</param>
|
||||
/// <param name="rule">A rule to be added to the current rules.</param>
|
||||
/// <returns>The Rewrite options.</returns>
|
||||
public static RewriteOptions Add(this RewriteOptions options, Rule rule)
|
||||
{
|
||||
options.Rules.Add(rule);
|
||||
return options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a rule to the current rules.
|
||||
/// </summary>
|
||||
/// <param name="options">The Rewrite options.</param>
|
||||
/// <param name="applyRule">A Func that checks and applies the rule.</param>
|
||||
/// <returns></returns>
|
||||
public static RewriteOptions Add(this RewriteOptions options, Func<RewriteContext, RuleResult> applyRule)
|
||||
{
|
||||
options.Rules.Add(new DelegateRule(applyRule));
|
||||
return options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rewrites the path if the regex matches the HttpContext's PathString
|
||||
/// </summary>
|
||||
/// <param name="options">The Rewrite options.</param>
|
||||
/// <param name="regex">The regex string to compare with.</param>
|
||||
/// <param name="urlPattern">If the regex matches, what to replace HttpContext with.</param>
|
||||
/// <returns>The Rewrite options.</returns>
|
||||
public static RewriteOptions Rewrite(this RewriteOptions options, string regex, string urlPattern)
|
||||
{
|
||||
return Rewrite(options, regex, urlPattern, stopProcessing: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rewrites the path if the regex matches the HttpContext's PathString
|
||||
/// </summary>
|
||||
/// <param name="options">The Rewrite options.</param>
|
||||
/// <param name="regex">The regex string to compare with.</param>
|
||||
/// <param name="urlPattern">If the regex matches, what to replace the uri with.</param>
|
||||
/// <param name="stopProcessing">If the regex matches, conditionally stop processing other rules.</param>
|
||||
/// <returns>The Rewrite options.</returns>
|
||||
public static RewriteOptions Rewrite(this RewriteOptions options, string regex, string urlPattern, bool stopProcessing)
|
||||
{
|
||||
var builder = new UrlRewriteRuleBuilder();
|
||||
var pattern = new InputParser().ParseInputString(urlPattern);
|
||||
|
||||
builder.AddUrlMatch(regex);
|
||||
builder.AddUrlAction(pattern, actionType: ActionType.Rewrite, stopProcessing: stopProcessing);
|
||||
options.Rules.Add(builder.Build());
|
||||
return options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redirect the request if the regex matches the HttpContext's PathString
|
||||
/// </summary>
|
||||
/// <param name="options">The Rewrite options.</param>
|
||||
/// <param name="regex">The regex string to compare with.</param>
|
||||
/// <param name="urlPattern">If the regex matches, what to replace the uri with.</param>
|
||||
/// <returns>The Rewrite options.</returns>
|
||||
public static RewriteOptions Redirect(this RewriteOptions options, string regex, string urlPattern)
|
||||
{
|
||||
return Redirect(options, regex, urlPattern, statusCode: 302);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redirect the request if the regex matches the HttpContext's PathString
|
||||
/// </summary>
|
||||
/// <param name="options">The Rewrite options.</param>
|
||||
/// <param name="regex">The regex string to compare with.</param>
|
||||
/// <param name="urlPattern">If the regex matches, what to replace the uri with.</param>
|
||||
/// <param name="statusCode">The status code to add to the response.</param>
|
||||
/// <returns>The Rewrite options.</returns>
|
||||
public static RewriteOptions Redirect(this RewriteOptions options, string regex, string urlPattern, int statusCode)
|
||||
{
|
||||
var builder = new UrlRewriteRuleBuilder();
|
||||
var pattern = new InputParser().ParseInputString(urlPattern);
|
||||
|
||||
builder.AddUrlMatch(regex);
|
||||
builder.AddUrlAction(pattern, actionType: ActionType.Redirect, stopProcessing: false);
|
||||
options.Rules.Add(builder.Build());
|
||||
return options;
|
||||
}
|
||||
|
||||
// TODO 301 overload
|
||||
|
||||
/// <summary>
|
||||
/// Redirect a request to https if the incoming request is http
|
||||
/// </summary>
|
||||
/// <param name="options">The Rewrite options.</param>
|
||||
public static RewriteOptions RedirectToHttps(this RewriteOptions options)
|
||||
{
|
||||
return RedirectToHttps(options, statusCode: 302, sslPort: null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redirect a request to https if the incoming request is http
|
||||
/// </summary>
|
||||
/// <param name="options">The Rewrite options.</param>
|
||||
/// <param name="statusCode">The status code to add to the response.</param>
|
||||
public static RewriteOptions RedirectToHttps(this RewriteOptions options, int statusCode)
|
||||
{
|
||||
return RedirectToHttps(options, statusCode, sslPort: null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redirect a request to https if the incoming request is http
|
||||
/// </summary>
|
||||
/// <param name="options">The Rewrite options.</param>
|
||||
/// <param name="statusCode">The status code to add to the response.</param>
|
||||
/// <param name="sslPort">The SSL port to add to the response.</param>
|
||||
public static RewriteOptions RedirectToHttps(this RewriteOptions options, int statusCode, int? sslPort)
|
||||
{
|
||||
options.Rules.Add(new RedirectToHttpsRule { StatusCode = statusCode, SSLPort = sslPort });
|
||||
return options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
// make this public and doc comements
|
||||
public abstract class Rule
|
||||
{
|
||||
public abstract RuleResult ApplyRule(RewriteContext context);
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
public class RuleResult
|
||||
{
|
||||
public static RuleResult Continue = new RuleResult { Result = RuleTerminiation.Continue };
|
||||
public static RuleResult ResponseComplete = new RuleResult { Result = RuleTerminiation.ResponseComplete };
|
||||
public static RuleResult StopRules = new RuleResult { Result = RuleTerminiation.StopRules };
|
||||
public static RuleResult Continue = new RuleResult { Result = RuleTermination.Continue };
|
||||
public static RuleResult ResponseComplete = new RuleResult { Result = RuleTermination.ResponseComplete };
|
||||
public static RuleResult StopRules = new RuleResult { Result = RuleTermination.StopRules };
|
||||
|
||||
public RuleTerminiation Result { get; set; }
|
||||
public RuleTermination Result { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
public enum RuleTerminiation
|
||||
public enum RuleTermination
|
||||
{
|
||||
Continue,
|
||||
ResponseComplete,
|
||||
|
|
@ -8,24 +8,24 @@ using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite;
|
|||
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
public static class UrlRewriteExtensions
|
||||
public static class UrlRewriteOptionsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Imports rules from a mod_rewrite file and adds the rules to current rules.
|
||||
/// </summary>
|
||||
/// <param name="options">The UrlRewrite options.</param>
|
||||
/// <param name="hostingEnv"></param>
|
||||
/// <param name="hostingEnvironment"></param>
|
||||
/// <param name="filePath">The path to the file containing urlrewrite rules.</param>
|
||||
public static RewriteOptions ImportFromUrlRewrite(this RewriteOptions options, IHostingEnvironment hostingEnv, string filePath)
|
||||
public static RewriteOptions ImportFromUrlRewrite(this RewriteOptions options, IHostingEnvironment hostingEnvironment, string filePath)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
if (hostingEnv == null)
|
||||
if (hostingEnvironment == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostingEnv));
|
||||
throw new ArgumentNullException(nameof(hostingEnvironment));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(filePath))
|
||||
|
|
@ -33,35 +33,36 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
throw new ArgumentException(nameof(filePath));
|
||||
}
|
||||
|
||||
var path = Path.Combine(hostingEnv.ContentRootPath, filePath);
|
||||
var path = Path.Combine(hostingEnvironment.ContentRootPath, filePath);
|
||||
using (var stream = File.OpenRead(path))
|
||||
{
|
||||
options.Rules.AddRange(new FileParser().Parse(new StreamReader(stream)));
|
||||
};
|
||||
return options;
|
||||
return ImportFromUrlRewrite(options, new StreamReader(stream));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imports rules from a mod_rewrite file and adds the rules to current rules.
|
||||
/// </summary>
|
||||
/// <param name="options">The UrlRewrite options.</param>
|
||||
/// <param name="stream">The text reader stream.</param>
|
||||
public static RewriteOptions ImportFromUrlRewrite(this RewriteOptions options, TextReader stream)
|
||||
/// <param name="reader">The text reader stream.</param>
|
||||
public static RewriteOptions ImportFromUrlRewrite(this RewriteOptions options, TextReader reader)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
if (stream == null)
|
||||
if (reader == null)
|
||||
{
|
||||
throw new ArgumentException(nameof(stream));
|
||||
throw new ArgumentException(nameof(reader));
|
||||
}
|
||||
|
||||
using (stream)
|
||||
var rules = new UrlRewriteFileParser().Parse(reader);
|
||||
|
||||
foreach (var rule in rules)
|
||||
{
|
||||
options.Rules.AddRange(new FileParser().Parse(stream));
|
||||
};
|
||||
options.Rules.Add(rule);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.CodeRules
|
|||
[Fact]
|
||||
public async Task CheckRewritePath()
|
||||
{
|
||||
var options = new RewriteOptions().RewriteRule("(.*)", "http://example.com/{R:1}");
|
||||
var options = new RewriteOptions().Rewrite("(.*)", "http://example.com/{R:1}");
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.CodeRules
|
|||
[Fact]
|
||||
public async Task CheckRedirectPath()
|
||||
{
|
||||
var options = new RewriteOptions().RedirectRule("(.*)","http://example.com/{R:1}", statusCode: 301);
|
||||
var options = new RewriteOptions().Redirect("(.*)","http://example.com/{R:1}", statusCode: 301);
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -52,25 +52,6 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.CodeRules
|
|||
Assert.Equal(response.Headers.Location.OriginalString, "http://example.com/foo");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckRewriteToHttps()
|
||||
{
|
||||
var options = new RewriteOptions().RewriteToHttps();
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseRewriter(options);
|
||||
app.UseRewriter(options);
|
||||
app.Run(context => context.Response.WriteAsync(
|
||||
context.Request.Scheme));
|
||||
});
|
||||
var server = new TestServer(builder);
|
||||
|
||||
var response = await server.CreateClient().GetStringAsync(new Uri("http://example.com"));
|
||||
|
||||
Assert.Equal(response, "https");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckRedirectToHttps()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_RewritePathWhenMatching()
|
||||
{
|
||||
var options = new RewriteOptions().AddModRewriteRule("RewriteRule /hey/(.*) /$1 ");
|
||||
var options = new RewriteOptions().ImportFromModRewrite(new StringReader("RewriteRule /hey/(.*) /$1 "));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -34,8 +34,8 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_RewritePathTerminatesOnFirstSuccessOfRule()
|
||||
{
|
||||
var options = new RewriteOptions().AddModRewriteRule("RewriteRule /hey/(.*) /$1 [L]")
|
||||
.AddModRewriteRule("RewriteRule /hello /what");
|
||||
var options = new RewriteOptions().ImportFromModRewrite(new StringReader("RewriteRule /hey/(.*) /$1 [L]"))
|
||||
.ImportFromModRewrite(new StringReader("RewriteRule /hello /what"));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -52,8 +52,8 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_RewritePathDoesNotTerminateOnFirstSuccessOfRule()
|
||||
{
|
||||
var options = new RewriteOptions().AddModRewriteRule("RewriteRule /hey/(.*) /$1")
|
||||
.AddModRewriteRule("RewriteRule /hello /what");
|
||||
var options = new RewriteOptions().ImportFromModRewrite(new StringReader("RewriteRule /hey/(.*) /$1"))
|
||||
.ImportFromModRewrite(new StringReader("RewriteRule /hello /what"));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite;
|
|||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
||||
{
|
||||
public class TestStringParserTests
|
||||
{
|
||||
|
|
@ -119,7 +119,7 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
[InlineData(@"%a", "Cannot parse '%a' to integer at string index: '1'")] // invalid character after %
|
||||
[InlineData(@"$a", "Cannot parse '$a' to integer at string index: '1'")] // invalid character after $
|
||||
[InlineData(@"%{asdf", "Missing close brace for parameter at string index: '6'")] // no closing } with characters
|
||||
public void ConditionParser_Bad(string testString, string expected)
|
||||
public void ConditionParser_InvalidInput(string testString, string expected)
|
||||
{
|
||||
var ex = Assert.Throws<FormatException>(() => new TestStringParser().Parse(testString));
|
||||
Assert.Equal(ex.Message, expected);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class ConditionMatchSegmentTests
|
||||
{
|
||||
|
||||
[Theory]
|
||||
[InlineData(1, "foo")]
|
||||
[InlineData(2, "bar")]
|
||||
[InlineData(3, "baz")]
|
||||
public void ConditionMatch_AssertBackreferencesObtainsCorrectValue(int index, string expected)
|
||||
{
|
||||
// Arrange
|
||||
var condMatch = CreateTestMatch();
|
||||
var segment = new ConditionMatchSegment(index);
|
||||
|
||||
// Act
|
||||
var results = segment.Evaluate(null, null, condMatch);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, results);
|
||||
}
|
||||
|
||||
private static MatchResults CreateTestMatch()
|
||||
{
|
||||
var match = Regex.Match("foo/bar/baz", "(.*)/(.*)/(.*)");
|
||||
return new MatchResults {BackReference = match.Groups, Success = match.Success};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class DateTimeSegmentTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("TIME_YEAR")]
|
||||
[InlineData("TIME_MON")]
|
||||
[InlineData("TIME_DAY")]
|
||||
[InlineData("TIME_HOUR")]
|
||||
[InlineData("TIME_MIN")]
|
||||
[InlineData("TIME_SEC")]
|
||||
[InlineData("TIME_WDAY")]
|
||||
[InlineData("TIME")]
|
||||
public void DateTime_AssertDoesntThrowOnCheckOfSegment(string input)
|
||||
{
|
||||
// Arrange
|
||||
var segment = new DateTimeSegment(input);
|
||||
|
||||
// Act
|
||||
var results = segment.Evaluate(null, null, null);
|
||||
|
||||
// TODO testing dates is hard, could use moq
|
||||
// currently just assert that the segment doesn't throw.
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("foo", "Unsupported segment: 'foo'")]
|
||||
[InlineData("wow", "Unsupported segment: 'wow'")]
|
||||
public void DateTime_AssertThrowsOnInvalidInput(string input, string expected)
|
||||
{
|
||||
|
||||
// Act And Assert
|
||||
var ex = Assert.Throws<FormatException>(() => new DateTimeSegment(input));
|
||||
Assert.Equal(ex.Message, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class HeaderSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void HeaderSegment_AssertGettingWithHeaderReturnsCorrectValue()
|
||||
{
|
||||
// Arrange
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
|
||||
context.HttpContext.Request.Headers[HeaderNames.Location] = "foo";
|
||||
var segment = new HeaderSegment(HeaderNames.Location);
|
||||
|
||||
// Act
|
||||
var results = segment.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("foo", results);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HeaderSegment_AssertGettingANonExistantHeaderReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
var segment = new HeaderSegment(HeaderNames.Location);
|
||||
|
||||
// Act
|
||||
var results = segment.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Null(results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class IsHttpsModSegmentTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("http", "off")]
|
||||
[InlineData("https", "on")]
|
||||
public void IsHttps_AssertCorrectBehaviorWhenProvidedHttpContext(string input, string expected)
|
||||
{
|
||||
// Arrange
|
||||
var segement = new IsHttpsModSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Request.Scheme = input;
|
||||
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class IsHttpsSegmentTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("http", "OFF")]
|
||||
[InlineData("https", "ON")]
|
||||
public void IsHttps_AssertCorrectBehaviorWhenProvidedHttpContext(string input, string expected)
|
||||
{
|
||||
// Arrange
|
||||
var segement = new IsHttpsSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Request.Scheme = input;
|
||||
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class IsIPV6SegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void IsIPv6_AssertNullRemoteIpAddressReportsCorrectValue()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new IsIPV6Segment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Connection.RemoteIpAddress = null;
|
||||
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("off", results);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsIPv6_AssertCorrectBehaviorWhenIPv6IsUsed()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new IsIPV6Segment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Connection.RemoteIpAddress = IPAddress.Parse("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
|
||||
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("on", results);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsIPv6_AssertCorrectBehaviorWhenIPv4IsUsed()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new IsIPV6Segment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Connection.RemoteIpAddress = IPAddress.Parse("20.30.40.50");
|
||||
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("off", results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class LiteralSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void LiteralSegment_AssertSegmentIsCorrect()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new LiteralSegment("foo");
|
||||
|
||||
// Act
|
||||
var results = segement.Evaluate(null, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("foo", results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class LocalAddressSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void LocalAddress_AssertSegmentIsCorrect()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new LocalAddressSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Connection.LocalIpAddress = IPAddress.Parse("20.30.40.50");
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("20.30.40.50", results);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LocalAddress_AssertNullLocalIpAddressReturnsNull()
|
||||
{
|
||||
var segement = new LocalAddressSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Connection.LocalIpAddress = null;
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Null( results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
|
||||
using System.Globalization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class LocalPortSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void LocalPortSegment_AssertSegmentIsCorrect()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new LocalPortSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Connection.LocalPort = 800;
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("800", results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class QueryStringSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void QueryString_AssertSegmentIsCorrect()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new QueryStringSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Request.QueryString = new QueryString("?hey=1");
|
||||
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("?hey=1", results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class RemoteAddressSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void RemoteAddress_AssertSegmentIsCorrect()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new RemoteAddressSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Connection.RemoteIpAddress = IPAddress.Parse("20.30.40.50");
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("20.30.40.50", results);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoteAddress_AssertNullLocalIpAddressReturnsNull()
|
||||
{
|
||||
var segement = new RemoteAddressSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Connection.RemoteIpAddress = null;
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Null(results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class RemotePortSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void RemotePort_AssertSegmentIsCorrect()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new RemotePortSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Connection.RemotePort = 800;
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("800", results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class RequestFilenameSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void RequestFilename_AssertSegmentIsCorrect()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new RequestFileNameSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Request.Path = new PathString("/foo/bar");
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("/foo/bar", results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class RequestMethodSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void RequestMethod_AssertSegmentIsCorrect()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new RequestMethodSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Request.Method = "GET";
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("GET", results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class RuleMatchSegmentTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(1, "foo")]
|
||||
[InlineData(2, "bar")]
|
||||
[InlineData(3, "baz")]
|
||||
public void RuleMatch_AssertBackreferencesObtainsCorrectValue(int index, string expected)
|
||||
{
|
||||
// Arrange
|
||||
var ruleMatch = CreateTestMatch();
|
||||
var segment = new RuleMatchSegment(index);
|
||||
|
||||
// Act
|
||||
var results = segment.Evaluate(null, ruleMatch, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, results);
|
||||
}
|
||||
|
||||
private static MatchResults CreateTestMatch()
|
||||
{
|
||||
var match = Regex.Match("foo/bar/baz", "(.*)/(.*)/(.*)");
|
||||
return new MatchResults { BackReference = match.Groups, Success = match.Success };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class SchemeSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void SchemeSegment_AssertSegmentIsCorrect()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new SchemeSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Request.Scheme = "http";
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("http", results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class ServerProtocolSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void ServerProtocol_AssertSegmentIsCorrect()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new ServerProtocolSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Features.Set<IHttpRequestFeature>(new HttpRequestFeature { Protocol = "http" });
|
||||
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("http", results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class ToLowerSegmentTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Hello", "hello")]
|
||||
[InlineData("WHAT", "what")]
|
||||
[InlineData("hey", "hey")]
|
||||
public void ToLower_AssertLowerCaseWorksAppropriately(string input, string expected)
|
||||
{
|
||||
// Arrange
|
||||
var pattern = new Pattern(new List<PatternSegment>());
|
||||
pattern.PatternSegments.Add(new LiteralSegment(input));
|
||||
var segement = new ToLowerSegment(pattern);
|
||||
var context = new RewriteContext();
|
||||
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class UrlEncodeSegmentTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(" ", "%20")]
|
||||
[InlineData("x&y", "x%26y")]
|
||||
[InlineData("hey", "hey")]
|
||||
public void ToLower_AssertLowerCaseWorksAppropriately(string input, string expected)
|
||||
{
|
||||
// Arrange
|
||||
var pattern = new Pattern(new List<PatternSegment>());
|
||||
pattern.PatternSegments.Add(new LiteralSegment(input));
|
||||
var segement = new UrlEncodeSegment(pattern);
|
||||
var context = new RewriteContext();
|
||||
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
||||
{
|
||||
public class UrlSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void LocalPortSegment_AssertSegmentIsCorrect()
|
||||
{
|
||||
// Arrange
|
||||
var segement = new UrlSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Request.Path = new PathString("/foo/bar");
|
||||
// Act
|
||||
var results = segement.Evaluate(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("/foo/bar", results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlActions;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.UrlActions
|
||||
{
|
||||
public class ForbiddenActionTests
|
||||
{
|
||||
[Fact]
|
||||
public void Forbidden_Verify403IsInStatusCode()
|
||||
{
|
||||
// Arrange
|
||||
var context = new RewriteContext {HttpContext = new DefaultHttpContext()};
|
||||
var action = new ForbiddenAction();
|
||||
|
||||
// Act
|
||||
var results = action.ApplyAction(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(results.Result, RuleTermination.ResponseComplete);
|
||||
Assert.Equal(context.HttpContext.Response.StatusCode, StatusCodes.Status403Forbidden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlActions;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.UrlActions
|
||||
{
|
||||
public class GoneActionTests
|
||||
{
|
||||
[Fact]
|
||||
public void Gone_Verify410IsInStatusCode()
|
||||
{
|
||||
// Arrange
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
var action = new GoneAction();
|
||||
|
||||
// Act
|
||||
var results = action.ApplyAction(context, null, null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(results.Result, RuleTermination.ResponseComplete);
|
||||
Assert.Equal(context.HttpContext.Response.StatusCode, StatusCodes.Status410Gone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -29,13 +29,13 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
|
||||
var expected = new List<UrlRewriteRule>();
|
||||
expected.Add(CreateTestRule(new List<Condition>(),
|
||||
Url: "^article/([0-9]+)/([_0-9a-z-]+)",
|
||||
url: "^article/([0-9]+)/([_0-9a-z-]+)",
|
||||
name: "Rewrite to article.aspx",
|
||||
actionType: ActionType.Rewrite,
|
||||
pattern: "article.aspx?id={R:1}&title={R:2}"));
|
||||
|
||||
// act
|
||||
var res = new FileParser().Parse(new StringReader(xml));
|
||||
var res = new UrlRewriteFileParser().Parse(new StringReader(xml));
|
||||
|
||||
// assert
|
||||
AssertUrlRewriteRuleEquality(res, expected);
|
||||
|
|
@ -66,13 +66,13 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
|
||||
var expected = new List<UrlRewriteRule>();
|
||||
expected.Add(CreateTestRule(condList,
|
||||
Url: "^article/([0-9]+)/([_0-9a-z-]+)",
|
||||
url: "^article/([0-9]+)/([_0-9a-z-]+)",
|
||||
name: "Rewrite to article.aspx",
|
||||
actionType: ActionType.Rewrite,
|
||||
pattern: "article.aspx?id={R:1}&title={R:2}"));
|
||||
|
||||
// act
|
||||
var res = new FileParser().Parse(new StringReader(xml));
|
||||
var res = new UrlRewriteFileParser().Parse(new StringReader(xml));
|
||||
|
||||
// assert
|
||||
AssertUrlRewriteRuleEquality(res, expected);
|
||||
|
|
@ -110,18 +110,18 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
|
||||
var expected = new List<UrlRewriteRule>();
|
||||
expected.Add(CreateTestRule(condList,
|
||||
Url: "^article/([0-9]+)/([_0-9a-z-]+)",
|
||||
url: "^article/([0-9]+)/([_0-9a-z-]+)",
|
||||
name: "Rewrite to article.aspx",
|
||||
actionType: ActionType.Rewrite,
|
||||
pattern: "article.aspx?id={R:1}&title={R:2}"));
|
||||
expected.Add(CreateTestRule(condList,
|
||||
Url: "^article/([0-9]+)/([_0-9a-z-]+)",
|
||||
url: "^article/([0-9]+)/([_0-9a-z-]+)",
|
||||
name: "Rewrite to another article.aspx",
|
||||
actionType: ActionType.Rewrite,
|
||||
pattern: "article.aspx?id={R:1}&title={R:2}"));
|
||||
|
||||
// act
|
||||
var res = new FileParser().Parse(new StringReader(xml));
|
||||
var res = new UrlRewriteFileParser().Parse(new StringReader(xml));
|
||||
|
||||
// assert
|
||||
AssertUrlRewriteRuleEquality(res, expected);
|
||||
|
|
@ -135,7 +135,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
bool enabled = true,
|
||||
PatternSyntax patternSyntax = PatternSyntax.ECMAScript,
|
||||
bool stopProcessing = false,
|
||||
string Url = "",
|
||||
string url = "",
|
||||
bool ignoreCase = true,
|
||||
bool negate = false,
|
||||
ActionType actionType = ActionType.None,
|
||||
|
|
@ -145,22 +145,12 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
RedirectType redirectType = RedirectType.Permanent
|
||||
)
|
||||
{
|
||||
return new UrlRewriteRule
|
||||
{
|
||||
Action = new RewriteAction(RuleTerminiation.Continue, new InputParser().ParseInputString(Url), clearQuery: false),
|
||||
Name = name,
|
||||
Enabled = enabled,
|
||||
InitialMatch = new RegexMatch(new Regex("^OFF$"), false)
|
||||
{
|
||||
},
|
||||
Conditions = new Conditions
|
||||
{
|
||||
ConditionList = conditions
|
||||
}
|
||||
};
|
||||
return new UrlRewriteRule(name, new RegexMatch(new Regex("^OFF$"), false), conditions,
|
||||
new RewriteAction(RuleTermination.Continue, new InputParser().ParseInputString(url), clearQuery: false));
|
||||
}
|
||||
|
||||
private void AssertUrlRewriteRuleEquality(List<UrlRewriteRule> actual, List<UrlRewriteRule> expected)
|
||||
// TODO make rules comparable?
|
||||
private void AssertUrlRewriteRuleEquality(IList<UrlRewriteRule> actual, IList<UrlRewriteRule> expected)
|
||||
{
|
||||
Assert.Equal(actual.Count, expected.Count);
|
||||
for (var i = 0; i < actual.Count; i++)
|
||||
|
|
@ -169,23 +159,22 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
var r2 = expected[i];
|
||||
|
||||
Assert.Equal(r1.Name, r2.Name);
|
||||
Assert.Equal(r1.Enabled, r2.Enabled);
|
||||
|
||||
if (r1.Conditions == null)
|
||||
{
|
||||
Assert.Equal(r2.Conditions.ConditionList.Count, 0);
|
||||
Assert.Equal(r2.Conditions.Count, 0);
|
||||
}
|
||||
else if (r2.Conditions == null)
|
||||
{
|
||||
Assert.Equal(r1.Conditions.ConditionList.Count, 0);
|
||||
Assert.Equal(r1.Conditions.Count, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Equal(r1.Conditions.ConditionList.Count, r2.Conditions.ConditionList.Count);
|
||||
for (var j = 0; j < r1.Conditions.ConditionList.Count; j++)
|
||||
Assert.Equal(r1.Conditions.Count, r2.Conditions.Count);
|
||||
for (var j = 0; j < r1.Conditions.Count; j++)
|
||||
{
|
||||
var c1 = r1.Conditions.ConditionList[j];
|
||||
var c2 = r2.Conditions.ConditionList[j];
|
||||
var c1 = r1.Conditions[j];
|
||||
var c2 = r2.Conditions[j];
|
||||
Assert.Equal(c1.Input.PatternSegments.Count, c2.Input.PatternSegments.Count);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
public void ThrowFormatExceptionWithCorrectMessage(string input, string expected)
|
||||
{
|
||||
// Arrange, Act, Assert
|
||||
var ex = Assert.Throws<FormatException>(() => new FileParser().Parse(new StringReader(input)));
|
||||
var ex = Assert.Throws<FormatException>(() => new UrlRewriteFileParser().Parse(new StringReader(input)));
|
||||
Assert.Equal(ex.Message, expected);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
{
|
||||
|
||||
var context = new DefaultHttpContext();
|
||||
return new RewriteContext { HttpContext = context, FileProvider = null };
|
||||
return new RewriteContext { HttpContext = context, StaticFileProvider = null };
|
||||
}
|
||||
|
||||
private MatchResults CreateTestRuleMatch()
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
|
||||
var response = await server.CreateClient().GetAsync("article/10/hey");
|
||||
|
||||
Assert.Equal(response.Headers.Location.OriginalString, "article.aspx?id=10&title=hey");
|
||||
Assert.Equal(response.Headers.Location.OriginalString, "/article.aspx?id=10&title=hey");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -112,7 +112,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
|
||||
var response = await server.CreateClient().GetAsync("HElLo");
|
||||
|
||||
Assert.Equal(response.Headers.Location.OriginalString, "hello");
|
||||
Assert.Equal(response.Headers.Location.OriginalString, "/hello");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -139,7 +139,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
|
||||
var response = await server.CreateClient().GetAsync("hey/hello/");
|
||||
|
||||
Assert.Equal(response.Headers.Location.OriginalString, "hey/hello");
|
||||
Assert.Equal(response.Headers.Location.OriginalString, "/hey/hello");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -166,7 +166,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
|
||||
var response = await server.CreateClient().GetAsync("hey/hello");
|
||||
|
||||
Assert.Equal(response.Headers.Location.OriginalString, "hey/hello/");
|
||||
Assert.Equal(response.Headers.Location.OriginalString, "/hey/hello/");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
||||
|
|
@ -28,11 +23,11 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
</rule>
|
||||
</rules>
|
||||
</rewrite>");
|
||||
var rules = new FileParser().Parse(xml);
|
||||
var rules = new UrlRewriteFileParser().Parse(xml);
|
||||
|
||||
Assert.Equal(rules.Count, 1);
|
||||
var ruleResults = rules.FirstOrDefault().ApplyRule(new RewriteContext {HttpContext = new DefaultHttpContext()});
|
||||
Assert.Equal(ruleResults.Result, RuleTerminiation.StopRules);
|
||||
Assert.Equal(ruleResults.Result, RuleTermination.StopRules);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -46,11 +41,11 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
</rule>
|
||||
</rules>
|
||||
</rewrite>");
|
||||
var rules = new FileParser().Parse(xml);
|
||||
var rules = new UrlRewriteFileParser().Parse(xml);
|
||||
|
||||
Assert.Equal(rules.Count, 1);
|
||||
var ruleResults = rules.FirstOrDefault().ApplyRule(new RewriteContext { HttpContext = new DefaultHttpContext() });
|
||||
Assert.Equal(ruleResults.Result, RuleTerminiation.Continue);
|
||||
Assert.Equal(ruleResults.Result, RuleTermination.Continue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue