Adds XML comments and feedback from 1on1 with Nate.
This commit is contained in:
parent
4a06b37280
commit
af2c1acee3
|
|
@ -1,3 +1,4 @@
|
|||
# Rewrite path with additional sub directory
|
||||
RewriteCond %{QUERY_STRING} id=20
|
||||
RewriteRule ^(.*)$ - [G]
|
||||
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC,OR]
|
||||
RewriteCond %{SERVER_PORT} !^5000$
|
||||
RewriteRule ^/(.*) http://www.example.com/$1 [L,R=302]
|
||||
|
|
@ -11,25 +11,16 @@ namespace RewriteSample
|
|||
{
|
||||
public class Startup
|
||||
{
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment hostingEnv)
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment hostingEnvironment)
|
||||
{
|
||||
// Four main use cases for Rewrite Options.
|
||||
// 1. Importing from a UrlRewrite file, which are IIS Rewrite rules.
|
||||
// This file is in xml format, starting with the <rewrite> tag.
|
||||
// 2. Importing from a mod_rewrite file, which are mod_rewrite rules.
|
||||
// This file is in standard mod_rewrite format which only contains rewrite information.
|
||||
// 3. Inline rules in code, where you can specify rules such as rewrites and redirects
|
||||
// based on certain conditions. Ex: RedirectToHttps will check if the request is https,
|
||||
// else it will redirect the request with https.
|
||||
// 4. Functional rules. If a user has a very specific function they would like to implement
|
||||
// (ex StringReplace) that are easy to implement in code, they can do so by calling
|
||||
// AddFunctionalRule(Func);
|
||||
// TODO make this startup do something useful.
|
||||
var options = new RewriteOptions()
|
||||
.AddRedirect("(.*)/$", "$1")
|
||||
.AddRewrite(@"app/(\d+)", "app?id=$1")
|
||||
.AddRedirectToHttps(302)
|
||||
.AddIISUrlRewrite(hostingEnvironment, "UrlRewrite.xml")
|
||||
.AddApacheModRewrite(hostingEnvironment, "Rewrite.txt");
|
||||
|
||||
app.UseRewriter(new RewriteOptions()
|
||||
.Rewrite(@"foo/(\d+)", "foo?id=$1")
|
||||
.ImportFromUrlRewrite(hostingEnv, "UrlRewrite.xml")
|
||||
.ImportFromModRewrite(hostingEnv, "Rewrite.txt"));
|
||||
app.UseRewriter(options);
|
||||
|
||||
app.Run(context => context.Response.WriteAsync($"Rewritten Url: {context.Request.Path + context.Request.QueryString}"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
<rewrite>
|
||||
<rules>
|
||||
<rule name="" stopProcessing="true">
|
||||
<match url="foo/bar" />
|
||||
<action type="Redirect" redirectType="Found" url="foo/" />
|
||||
<match url="(.*)" />
|
||||
<conditions>
|
||||
<add input="{QUERY_STRING}" pattern="id=20" />
|
||||
</conditions>
|
||||
<action type="Rewrite" url="app?id=10" appendQueryString="false"/>
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
|
|
@ -8,7 +8,10 @@ using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite;
|
|||
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
public static class ModRewriteOptionsExtensions
|
||||
/// <summary>
|
||||
/// Apache mod_rewrite extensions on top of the <see cref="RewriteOptions"/>
|
||||
/// </summary>
|
||||
public static class ApacheModRewriteOptionsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Imports rules from a mod_rewrite file and adds the rules to current rules.
|
||||
|
|
@ -16,7 +19,7 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
/// <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 hostingEnvironment, string filePath)
|
||||
public static RewriteOptions AddApacheModRewrite(this RewriteOptions options, IHostingEnvironment hostingEnvironment, string filePath)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
|
|
@ -36,7 +39,7 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
var path = Path.Combine(hostingEnvironment.ContentRootPath, filePath);
|
||||
using (var stream = File.OpenRead(path))
|
||||
{
|
||||
return options.ImportFromModRewrite(new StreamReader(stream));
|
||||
return options.AddApacheModRewrite(new StreamReader(stream));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -44,8 +47,8 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
/// Imports rules from a mod_rewrite file and adds the rules to current rules.
|
||||
/// </summary>
|
||||
/// <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)
|
||||
/// <param name="reader">A stream of mod_rewrite rules.</param>
|
||||
public static RewriteOptions AddApacheModRewrite(this RewriteOptions options, TextReader reader)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
|
|
@ -8,7 +8,10 @@ using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite;
|
|||
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
public static class UrlRewriteOptionsExtensions
|
||||
/// <summary>
|
||||
/// IIS Url rewrite extensions on top of the <see cref="RewriteOptions"/>
|
||||
/// </summary>
|
||||
public static class IISUrlRewriteOptionsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Imports rules from a mod_rewrite file and adds the rules to current rules.
|
||||
|
|
@ -16,7 +19,7 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
/// <param name="options">The UrlRewrite options.</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 hostingEnvironment, string filePath)
|
||||
public static RewriteOptions AddIISUrlRewrite(this RewriteOptions options, IHostingEnvironment hostingEnvironment, string filePath)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
|
|
@ -36,7 +39,7 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
var path = Path.Combine(hostingEnvironment.ContentRootPath, filePath);
|
||||
using (var stream = File.OpenRead(path))
|
||||
{
|
||||
return ImportFromUrlRewrite(options, new StreamReader(stream));
|
||||
return AddIISUrlRewrite(options, new StreamReader(stream));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -45,7 +48,7 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
/// </summary>
|
||||
/// <param name="options">The UrlRewrite options.</param>
|
||||
/// <param name="reader">The text reader stream.</param>
|
||||
public static RewriteOptions ImportFromUrlRewrite(this RewriteOptions options, TextReader reader)
|
||||
public static RewriteOptions AddIISUrlRewrite(this RewriteOptions options, TextReader reader)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
|
|
@ -39,7 +39,6 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.CodeRules
|
|||
{
|
||||
var result = initMatchResults.Result(Replacement);
|
||||
var request = context.HttpContext.Request;
|
||||
|
||||
if (result.IndexOf("://", StringComparison.Ordinal) >= 0)
|
||||
{
|
||||
string scheme;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
{ "noescape", FlagType.NoEscape },
|
||||
{ "ns", FlagType.NoSubReq },
|
||||
{ "nosubreq", FlagType.NoSubReq },
|
||||
{ "or", FlagType.Or },
|
||||
{ "ornext", FlagType.Or },
|
||||
{ "p", FlagType.Proxy },
|
||||
{ "proxy", FlagType.Proxy },
|
||||
{ "pt", FlagType.PassThrough },
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PreActions;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlActions;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;
|
||||
|
||||
|
|
@ -13,19 +12,18 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
public class RuleBuilder
|
||||
{
|
||||
private IList<Condition> _conditions;
|
||||
private UrlAction _action;
|
||||
private IList<UrlAction> _actions = new List<UrlAction>();
|
||||
private UrlMatch _match;
|
||||
private List<PreAction> _preActions;
|
||||
|
||||
private readonly TimeSpan RegexTimeout = TimeSpan.FromMilliseconds(1);
|
||||
|
||||
public ModRewriteRule Build()
|
||||
{
|
||||
if (_action == null || _match == null)
|
||||
if (_actions.Count == 0 || _match == null)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot create ModRewriteRule without action and match");
|
||||
}
|
||||
return new ModRewriteRule(_match, _conditions, _action, _preActions);
|
||||
return new ModRewriteRule(_match, _conditions, _actions);
|
||||
}
|
||||
|
||||
public void AddRule(string rule)
|
||||
|
|
@ -169,31 +167,26 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
Flags flags)
|
||||
{
|
||||
// first create pre conditions
|
||||
if (_preActions == null)
|
||||
{
|
||||
_preActions = new List<PreAction>();
|
||||
}
|
||||
|
||||
string flag;
|
||||
if (flags.GetValue(FlagType.Cookie, out flag))
|
||||
{
|
||||
// parse cookie
|
||||
_preActions.Add(new ChangeCookiePreAction(flag));
|
||||
_actions.Add(new ChangeCookieAction(flag));
|
||||
}
|
||||
|
||||
if (flags.GetValue(FlagType.Env, out flag))
|
||||
{
|
||||
// parse env
|
||||
_preActions.Add(new ChangeEnvironmentPreAction(flag));
|
||||
_actions.Add(new ChangeEnvironmentAction(flag));
|
||||
}
|
||||
|
||||
if (flags.HasFlag(FlagType.Forbidden))
|
||||
{
|
||||
_action = new ForbiddenAction();
|
||||
_actions.Add(new ForbiddenAction());
|
||||
}
|
||||
else if (flags.HasFlag(FlagType.Gone))
|
||||
{
|
||||
_action = new GoneAction();
|
||||
_actions.Add(new GoneAction());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -210,13 +203,13 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
{
|
||||
throw new FormatException(Resources.FormatError_InputParserInvalidInteger(statusCode, -1));
|
||||
}
|
||||
_action = new RedirectAction(res, pattern, queryStringAppend, queryStringDelete, escapeBackReference);
|
||||
_actions.Add(new RedirectAction(res, pattern, queryStringAppend, queryStringDelete, escapeBackReference));
|
||||
}
|
||||
else
|
||||
{
|
||||
var last = flags.HasFlag(FlagType.End) || flags.HasFlag(FlagType.Last);
|
||||
var termination = last ? RuleTermination.StopRules : RuleTermination.Continue;
|
||||
_action = new RewriteAction(termination, pattern, queryStringAppend, queryStringDelete, escapeBackReference);
|
||||
_actions.Add(new RewriteAction(termination, pattern, queryStringAppend, queryStringDelete, escapeBackReference));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,15 +10,13 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
|||
{
|
||||
public UrlMatch InitialMatch { get; }
|
||||
public IList<Condition> Conditions { get; }
|
||||
public UrlAction Action { get; }
|
||||
public IList<PreAction> PreActions { get; }
|
||||
public IList<UrlAction> Actions { get; }
|
||||
|
||||
public ModRewriteRule(UrlMatch initialMatch, IList<Condition> conditions, UrlAction urlAction, IList<PreAction> preActions)
|
||||
public ModRewriteRule(UrlMatch initialMatch, IList<Condition> conditions, IList<UrlAction> urlActions)
|
||||
{
|
||||
Conditions = conditions;
|
||||
InitialMatch = initialMatch;
|
||||
Action = urlAction;
|
||||
PreActions = preActions;
|
||||
Actions = urlActions;
|
||||
}
|
||||
|
||||
public override void ApplyRule(RewriteContext context)
|
||||
|
|
@ -46,12 +44,11 @@ namespace Microsoft.AspNetCore.Rewrite.Internal
|
|||
// 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);
|
||||
}
|
||||
|
||||
Action.ApplyAction(context, initMatchRes, condMatchRes);
|
||||
foreach (var action in Actions)
|
||||
{
|
||||
action.ApplyAction(context, initMatchRes, condMatchRes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
|||
{
|
||||
public class IsHttpsModSegment : PatternSegment
|
||||
{
|
||||
// Note: Mod rewrite pattern matches on lower case "on" and "off"
|
||||
// while IIS looks for capitalized "ON" and "OFF"
|
||||
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||
{
|
||||
return context.HttpContext.Request.IsHttps ? "on" : "off";
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@
|
|||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
|
||||
{
|
||||
public class IsHttpsSegment : PatternSegment
|
||||
{
|
||||
public class IsHttpsUrlSegment : PatternSegment
|
||||
{
|
||||
// Note: Mod rewrite pattern matches on lower case "on" and "off"
|
||||
// while IIS looks for capitalized "ON" and "OFF"
|
||||
public override string Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||
{
|
||||
return context.HttpContext.Request.IsHttps ? "ON" : "OFF";
|
||||
|
|
@ -1,12 +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
|
||||
{
|
||||
public abstract class PreAction
|
||||
{
|
||||
public abstract void ApplyAction(HttpContext context, MatchResults ruleMatch, MatchResults condMatch);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,17 +4,17 @@
|
|||
using System;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.PreActions
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
|
||||
{
|
||||
public class ChangeCookiePreAction : PreAction
|
||||
public class ChangeCookieAction : UrlAction
|
||||
{
|
||||
public ChangeCookiePreAction(string cookie)
|
||||
public ChangeCookieAction(string cookie)
|
||||
{
|
||||
// TODO
|
||||
throw new NotImplementedException(cookie);
|
||||
}
|
||||
|
||||
public override void ApplyAction(HttpContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||
public override void ApplyAction(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||
{
|
||||
// modify the cookies
|
||||
|
||||
|
|
@ -4,17 +4,17 @@
|
|||
using System;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.PreActions
|
||||
namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
|
||||
{
|
||||
public class ChangeEnvironmentPreAction : PreAction
|
||||
public class ChangeEnvironmentAction : UrlAction
|
||||
{
|
||||
public ChangeEnvironmentPreAction(string env)
|
||||
public ChangeEnvironmentAction(string env)
|
||||
{
|
||||
// TODO
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void ApplyAction(HttpContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||
public override void ApplyAction(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||
{
|
||||
// Do stuff to modify the env
|
||||
throw new NotImplementedException();
|
||||
|
|
@ -41,7 +41,6 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
|
|||
queryStringDelete: true,
|
||||
escapeBackReferences: false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void ApplyAction(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch)
|
||||
|
|
@ -58,7 +57,6 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
|
|||
{
|
||||
pattern = '/' + pattern;
|
||||
}
|
||||
|
||||
response.StatusCode = StatusCode;
|
||||
|
||||
// url can either contain the full url or the path and query
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions
|
|||
{
|
||||
var pattern = Url.Evaluate(context, ruleMatch, condMatch);
|
||||
var request = context.HttpContext.Request;
|
||||
|
||||
if (EscapeBackReferences)
|
||||
{
|
||||
// because escapebackreferences will be encapsulated by the pattern, just escape the pattern
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite
|
|||
case "HTTP_URL":
|
||||
return new UrlSegment();
|
||||
case "HTTPS":
|
||||
return new IsHttpsSegment();
|
||||
return new IsHttpsUrlSegment();
|
||||
case "LOCAL_ADDR":
|
||||
return new LocalAddressSegment();
|
||||
case "HTTP_PROXY_CONNECTION":
|
||||
|
|
|
|||
|
|
@ -9,15 +9,31 @@ using Microsoft.Extensions.Logging;
|
|||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// A context object for <see cref="RewriteMiddleware"/>
|
||||
/// </summary>
|
||||
public class RewriteContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets and sets the <see cref="HttpContext"/>
|
||||
/// </summary>
|
||||
public HttpContext HttpContext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the File Provider for file and directory checks.
|
||||
/// </summary>
|
||||
public IFileProvider StaticFileProvider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the logger
|
||||
/// </summary>
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A shared result that is set appropriately by each rule for the next action that
|
||||
/// should be take. See <see cref="RuleTermination"/>
|
||||
/// </summary>
|
||||
public RuleTermination Result { get; set; }
|
||||
|
||||
// PERF: share the same string builder per request
|
||||
internal StringBuilder Builder { get; set; } = new StringBuilder(64);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System;
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,14 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
/// </summary>
|
||||
public class RewriteOptions
|
||||
{
|
||||
// TODO doc comments
|
||||
/// <summary>
|
||||
/// A list of <see cref="Rule"/> that will be applied in order upon a request.
|
||||
/// </summary>
|
||||
public IList<Rule> Rules { get; } = new List<Rule>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the File Provider for file and directory checks.
|
||||
/// </summary>
|
||||
public IFileProvider StaticFileProvider { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,9 +44,9 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
/// <param name="regex">The regex string to compare with.</param>
|
||||
/// <param name="replacement">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 replacement)
|
||||
public static RewriteOptions AddRewrite(this RewriteOptions options, string regex, string replacement)
|
||||
{
|
||||
return Rewrite(options, regex, replacement, stopProcessing: false);
|
||||
return AddRewrite(options, regex, replacement, stopProcessing: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
/// <param name="replacement">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 replacement, bool stopProcessing)
|
||||
public static RewriteOptions AddRewrite(this RewriteOptions options, string regex, string replacement, bool stopProcessing)
|
||||
{
|
||||
options.Rules.Add(new RewriteRule(regex, replacement, stopProcessing));
|
||||
return options;
|
||||
|
|
@ -70,9 +70,9 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
/// <param name="regex">The regex string to compare with.</param>
|
||||
/// <param name="replacement">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 replacement)
|
||||
public static RewriteOptions AddRedirect(this RewriteOptions options, string regex, string replacement)
|
||||
{
|
||||
return Redirect(options, regex, replacement, statusCode: 302);
|
||||
return AddRedirect(options, regex, replacement, statusCode: 302);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -83,24 +83,30 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
/// <param name="replacement">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 replacement, int statusCode)
|
||||
public static RewriteOptions AddRedirect(this RewriteOptions options, string regex, string replacement, int statusCode)
|
||||
{
|
||||
options.Rules.Add(new RedirectRule(regex, replacement, statusCode));
|
||||
return options;
|
||||
}
|
||||
|
||||
public static RewriteOptions RedirectToHttpsPermanent(this RewriteOptions options)
|
||||
/// <summary>
|
||||
/// Redirect a request to https if the incoming request is http, with returning a 301
|
||||
/// status code for permanently redirected.
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
/// <returns></returns>
|
||||
public static RewriteOptions AddRedirectToHttpsPermanent(this RewriteOptions options)
|
||||
{
|
||||
return RedirectToHttps(options, statusCode: 301, sslPort: null);
|
||||
return AddRedirectToHttps(options, statusCode: 301, sslPort: null);
|
||||
}
|
||||
|
||||
/// <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)
|
||||
public static RewriteOptions AddRedirectToHttps(this RewriteOptions options)
|
||||
{
|
||||
return RedirectToHttps(options, statusCode: 302, sslPort: null);
|
||||
return AddRedirectToHttps(options, statusCode: 302, sslPort: null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -108,9 +114,9 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
/// </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)
|
||||
public static RewriteOptions AddRedirectToHttps(this RewriteOptions options, int statusCode)
|
||||
{
|
||||
return RedirectToHttps(options, statusCode, sslPort: null);
|
||||
return AddRedirectToHttps(options, statusCode, sslPort: null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -119,7 +125,7 @@ namespace Microsoft.AspNetCore.Rewrite
|
|||
/// <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)
|
||||
public static RewriteOptions AddRedirectToHttps(this RewriteOptions options, int statusCode, int? sslPort)
|
||||
{
|
||||
options.Rules.Add(new RedirectToHttpsRule { StatusCode = statusCode, SSLPort = sslPort });
|
||||
return options;
|
||||
|
|
|
|||
|
|
@ -3,10 +3,17 @@
|
|||
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
// make this public and doc comements
|
||||
// caller must set the context.Results field appropriately in rule.
|
||||
/// <summary>
|
||||
/// Represents an abstract rule.
|
||||
/// </summary>
|
||||
public abstract class Rule
|
||||
{
|
||||
/// <summary>
|
||||
/// Applies the rule.
|
||||
/// Implementations of ApplyRule should set the value for RewriteContext.Results
|
||||
/// (defaults to RuleTermination.Continue)
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public abstract void ApplyRule(RewriteContext context);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,22 @@
|
|||
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
/// <summary>
|
||||
/// An enum representing the result of a rule.
|
||||
/// </summary>
|
||||
public enum RuleTermination
|
||||
{
|
||||
/// <summary>
|
||||
/// Default value, continue applying rules.
|
||||
/// </summary>
|
||||
Continue,
|
||||
///<summary>
|
||||
/// Redirect occured, should send back new rewritten url.
|
||||
/// </summary>
|
||||
ResponseComplete,
|
||||
/// <summary>
|
||||
/// Stop applying rules and send context to the next middleware
|
||||
/// </summary>
|
||||
StopRules
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.CodeRules
|
|||
[Fact]
|
||||
public async Task CheckRewritePath()
|
||||
{
|
||||
var options = new RewriteOptions().Rewrite("(.*)", "http://example.com/$1");
|
||||
var options = new RewriteOptions().AddRewrite("(.*)", "http://example.com/$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().Redirect("(.*)","http://example.com/$1", statusCode: 301);
|
||||
var options = new RewriteOptions().AddRedirect("(.*)","http://example.com/$1", statusCode: 301);
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.CodeRules
|
|||
[Fact]
|
||||
public async Task CheckRedirectToHttps()
|
||||
{
|
||||
var options = new RewriteOptions().RedirectToHttps(statusCode: 301);
|
||||
var options = new RewriteOptions().AddRedirectToHttps(statusCode: 301);
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_RewritePathWhenMatching()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromModRewrite(new StringReader("RewriteRule /hey/(.*) /$1 "));
|
||||
var options = new RewriteOptions().AddApacheModRewrite(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().ImportFromModRewrite(new StringReader("RewriteRule /hey/(.*) /$1 [L]"))
|
||||
.ImportFromModRewrite(new StringReader("RewriteRule /hello /what"));
|
||||
var options = new RewriteOptions().AddApacheModRewrite(new StringReader("RewriteRule /hey/(.*) /$1 [L]"))
|
||||
.AddApacheModRewrite(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().ImportFromModRewrite(new StringReader("RewriteRule /hey/(.*) /$1"))
|
||||
.ImportFromModRewrite(new StringReader("RewriteRule /hello /what"));
|
||||
var options = new RewriteOptions().AddApacheModRewrite(new StringReader("RewriteRule /hey/(.*) /$1"))
|
||||
.AddApacheModRewrite(new StringReader("RewriteRule /hello /what"));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_ShouldIgnoreComments()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromModRewrite(new StringReader("#RewriteRule ^/hey/(.*) /$1 "));
|
||||
var options = new RewriteOptions().AddApacheModRewrite(new StringReader("#RewriteRule ^/hey/(.*) /$1 "));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_ShouldRewriteHomepage()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromModRewrite(new StringReader(@"RewriteRule ^/$ /homepage.html"));
|
||||
var options = new RewriteOptions().AddApacheModRewrite(new StringReader(@"RewriteRule ^/$ /homepage.html"));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_ShouldIgnorePorts()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromModRewrite(new StringReader(@"RewriteRule ^/$ /homepage.html"));
|
||||
var options = new RewriteOptions().AddApacheModRewrite(new StringReader(@"RewriteRule ^/$ /homepage.html"));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -121,7 +121,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_HandleNegatedRewriteRules()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromModRewrite(new StringReader(@"RewriteRule !^/$ /homepage.html"));
|
||||
var options = new RewriteOptions().AddApacheModRewrite(new StringReader(@"RewriteRule !^/$ /homepage.html"));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -138,7 +138,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_BackReferencesShouldBeApplied()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromModRewrite(new StringReader(@"RewriteRule (.*)\.aspx $1.php"));
|
||||
var options = new RewriteOptions().AddApacheModRewrite(new StringReader(@"RewriteRule (.*)\.aspx $1.php"));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -161,7 +161,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[InlineData("http://www.foo.org/homepage.ASPX", @"RewriteRule (.*)\.aspx $1.php [nocase]", "/homepage.php")]
|
||||
public async Task Invoke_ShouldHandleFlagNoCase(string url, string rule, string expected)
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromModRewrite(new StringReader(rule));
|
||||
var options = new RewriteOptions().AddApacheModRewrite(new StringReader(rule));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -179,7 +179,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
public async Task Invoke_CheckFullUrlWithOnlyPath()
|
||||
{
|
||||
var options = new RewriteOptions()
|
||||
.ImportFromModRewrite(new StringReader(@"RewriteRule (.+) http://www.example.com$1/"));
|
||||
.AddApacheModRewrite(new StringReader(@"RewriteRule (.+) http://www.example.com$1/"));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -197,7 +197,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
public async Task Invoke_CheckFullUrlWithUFlag()
|
||||
{
|
||||
var options = new RewriteOptions()
|
||||
.ImportFromModRewrite(new StringReader(@"RewriteRule (.+) http://www.example.com$1/"));
|
||||
.AddApacheModRewrite(new StringReader(@"RewriteRule (.+) http://www.example.com$1/"));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -215,7 +215,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
public async Task Invoke_CheckModFileConditions()
|
||||
{
|
||||
var options = new RewriteOptions()
|
||||
.ImportFromModRewrite(new StringReader(@"RewriteRule (.+) http://www.example.com$1/"));
|
||||
.AddApacheModRewrite(new StringReader(@"RewriteRule (.+) http://www.example.com$1/"));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -234,7 +234,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
public async Task Invoke_EnsureHttps(string input)
|
||||
{
|
||||
var options = new RewriteOptions()
|
||||
.ImportFromModRewrite(new StringReader("RewriteCond %{REQUEST_URI} /foo/ \nRewriteCond %{HTTPS} !on \nRewriteRule ^(.*)$ https://www.example.com$1 [R=301,L]"));
|
||||
.AddApacheModRewrite(new StringReader("RewriteCond %{REQUEST_URI} /foo/ \nRewriteCond %{HTTPS} !on \nRewriteRule ^(.*)$ https://www.example.com$1 [R=301,L]"));
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments
|
|||
public void IsHttps_AssertCorrectBehaviorWhenProvidedHttpContext(string input, string expected)
|
||||
{
|
||||
// Arrange
|
||||
var segement = new IsHttpsSegment();
|
||||
var segement = new IsHttpsUrlSegment();
|
||||
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
|
||||
context.HttpContext.Request.Scheme = input;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_RedirectPathToPathAndQuery()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"<rewrite>
|
||||
var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@"<rewrite>
|
||||
<rules>
|
||||
<rule name=""Rewrite to article.aspx"">
|
||||
<match url = ""^article/([0-9]+)/([_0-9a-z-]+)"" />
|
||||
|
|
@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_RewritePathToPathAndQuery()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"<rewrite>
|
||||
var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@"<rewrite>
|
||||
<rules>
|
||||
<rule name=""Rewrite to article.aspx"">
|
||||
<match url = ""^article/([0-9]+)/([_0-9a-z-]+)"" />
|
||||
|
|
@ -66,7 +66,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_RewriteBasedOnQueryStringParameters()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"<rewrite>
|
||||
var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@"<rewrite>
|
||||
<rules>
|
||||
<rule name=""Query String Rewrite"">
|
||||
<match url=""page\.asp$"" />
|
||||
|
|
@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_RedirectToLowerCase()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"<rewrite>
|
||||
var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@"<rewrite>
|
||||
<rules>
|
||||
<rule name=""Convert to lower case"" stopProcessing=""true"">
|
||||
<match url="".*[A-Z].*"" ignoreCase=""false"" />
|
||||
|
|
@ -118,7 +118,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_RedirectRemoveTrailingSlash()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"<rewrite>
|
||||
var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@"<rewrite>
|
||||
<rules>
|
||||
<rule name=""Remove trailing slash"" stopProcessing=""true"">
|
||||
<match url=""(.*)/$"" />
|
||||
|
|
@ -145,7 +145,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_RedirectAddTrailingSlash()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"<rewrite>
|
||||
var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@"<rewrite>
|
||||
<rules>
|
||||
<rule name=""Add trailing slash"" stopProcessing=""true"">
|
||||
<match url=""(.*[^/])$"" />
|
||||
|
|
@ -172,7 +172,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_RedirectToHttps()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"<rewrite>
|
||||
var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@"<rewrite>
|
||||
<rules>
|
||||
<rule name=""Redirect to HTTPS"" stopProcessing=""true"">
|
||||
<match url=""(.*)"" />
|
||||
|
|
@ -198,7 +198,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_RewriteToHttps()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"<rewrite>
|
||||
var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@"<rewrite>
|
||||
<rules>
|
||||
<rule name=""Rewrite to HTTPS"" stopProcessing=""true"">
|
||||
<match url=""(.*)"" />
|
||||
|
|
@ -230,7 +230,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
|
|||
[Fact]
|
||||
public async Task Invoke_ReverseProxyToAnotherSite()
|
||||
{
|
||||
var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@"<rewrite>
|
||||
var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@"<rewrite>
|
||||
<rules>
|
||||
<rule name=""Proxy"">
|
||||
<match url=""(.*)"" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue