From 5052a94cf7f81f194e1b77794594b4f46d82c363 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Wed, 27 Jul 2016 14:47:32 -0700 Subject: [PATCH] IIS UrlRewrite Rule Application --- samples/RewriteSample/Startup.cs | 9 +- samples/RewriteSample/UrlRewrite.xml | 17 +- ...Extensions.cs => CodeRewriteExtensions.cs} | 20 +- .../FunctionalRule.cs | 6 +- .../{ => Internal}/ModRewrite/Condition.cs | 2 +- .../ModRewrite/ConditionBuilder.cs | 2 +- .../ModRewrite/ConditionExpression.cs | 6 +- .../ModRewrite/ConditionFlagType.cs | 2 +- .../ModRewrite/ConditionFlags.cs | 2 +- .../ModRewrite/ConditionPatternParser.cs | 2 +- .../ModRewrite/ConditionTestStringParser.cs | 2 +- .../ModRewrite/ConditionType.cs | 2 +- .../ModRewrite/ExpressionCreator.cs | 5 +- .../{ => Internal}/ModRewrite/FileParser.cs | 4 +- .../{ => Internal}/ModRewrite/FlagParser.cs | 2 +- .../ModRewrite}/Operands/IntegerOperand.cs | 2 +- .../ModRewrite}/Operands/IntegerOperation.cs | 2 +- .../ModRewrite}/Operands/Operand.cs | 2 +- .../ModRewrite}/Operands/PropertyOperand.cs | 2 +- .../ModRewrite}/Operands/PropertyOperation.cs | 2 +- .../ModRewrite}/Operands/RegexOperand.cs | 2 +- .../ModRewrite}/Operands/StringOperand.cs | 2 +- .../ModRewrite}/Operands/StringOperation.cs | 2 +- .../ModRewrite/OperationType.cs | 2 +- .../ModRewrite/ParsedConditionExpression.cs | 2 +- .../{ => Internal}/ModRewrite/Pattern.cs | 4 +- .../ModRewrite/PatternSegment.cs | 2 +- .../{ => Internal}/ModRewrite/RuleBuilder.cs | 2 +- .../{ => Internal}/ModRewrite/RuleFlagType.cs | 2 +- .../{ => Internal}/ModRewrite/RuleFlags.cs | 2 +- .../ModRewrite/RuleRegexParser.cs | 2 +- .../{ => Internal}/ModRewrite/SegmentType.cs | 0 .../ModRewrite/ServerVariables.cs | 2 +- .../{ => Internal}/ModRewrite/Tokenizer.cs | 2 +- .../ModRewriteRule.cs | 21 +- .../{ => Internal}/ParserContext.cs | 0 .../{RuleAbstraction => Internal}/PathRule.cs | 12 +- .../{RuleAbstraction => Internal}/Rule.cs | 4 +- .../RuleExpression.cs | 4 +- .../Internal/RuleResult.cs | 14 + .../Internal/RuleTermination.cs | 7 +- .../SchemeRule.cs | 12 +- .../Transformation.cs | 2 +- .../{ => Internal}/UrlRewrite/ActionType.cs | 2 +- .../Internal/UrlRewrite/Condition.cs | 16 + .../Internal/UrlRewrite/Conditions.cs | 27 ++ .../{ => Internal}/UrlRewrite/InputParser.cs | 6 +- .../UrlRewrite/LogicalGrouping.cs | 2 +- .../Internal/UrlRewrite/MatchResults.cs | 13 + .../{ => Internal}/UrlRewrite/MatchType.cs | 2 +- .../UrlRewrite/ParsedCondition.cs} | 8 +- .../UrlRewrite/ParsedUrlAction.cs} | 8 +- .../UrlRewrite/ParsedUrlMatch.cs} | 7 +- .../{ => Internal}/UrlRewrite/Pattern.cs | 8 +- .../UrlRewrite/PatternSegment.cs | 6 +- .../PatternSegments/ConditionMatchSegment.cs | 7 +- .../PatternSegments/HeaderSegment.cs | 5 +- .../PatternSegments/IsHttpsSegment.cs | 5 +- .../PatternSegments/LiteralSegment.cs | 5 +- .../PatternSegments/LocalAddressSegment.cs | 5 +- .../PatternSegments/QueryStringSegment.cs | 5 +- .../PatternSegments/RemoteAddressSegment.cs | 5 +- .../PatternSegments/RemotePortSegment.cs | 5 +- .../PatternSegments/RequestFilenameSegment.cs | 15 + .../PatternSegments/RuleMatchSegment.cs | 7 +- .../PatternSegments/ToLowerSegment.cs | 5 +- .../PatternSegments/UrlEncodeSegment.cs | 5 +- .../UrlRewrite/PatternSegments/UrlSegment.cs | 7 +- .../UrlRewrite/PatternSyntax.cs | 2 +- .../{ => Internal}/UrlRewrite/RedirectType.cs | 2 +- .../{ => Internal}/UrlRewrite/RewriteTags.cs | 5 +- .../UrlRewrite/ServerVariables.cs | 11 +- .../Internal/UrlRewrite/UrlAction.cs | 14 + .../UrlRewrite/UrlActions/RedirectAction.cs | 42 +++ .../UrlActions/RedirectClearQueryAction.cs | 29 ++ .../UrlRewrite/UrlActions/RewriteAction.cs | 60 ++++ .../UrlRewrite/UrlActions/VoidAction.cs | 17 + .../Internal/UrlRewrite/UrlMatch.cs | 11 + .../UrlRewrite/UrlMatches/ExactMatch.cs | 24 ++ .../UrlRewrite/UrlMatches/IsDirectoryMatch.cs | 19 ++ .../UrlRewrite/UrlMatches/IsFileMatch.cs | 19 ++ .../UrlRewrite/UrlMatches/RegexMatch.cs | 27 ++ .../UrlRewrite/UrlRewriteFileParser.cs | 316 ++++++++++++++++++ .../Internal/UrlRewriteRule.cs | 41 +++ .../Microsoft.AspNetCore.Rewrite.xproj | 4 +- .../{ModRewrite => }/ModRewriteExtensions.cs | 45 +-- ...UrlRewriteContext.cs => RewriteContext.cs} | 2 +- .../RewriteExtensions.cs | 35 ++ ...riteMiddleware.cs => RewriteMiddleware.cs} | 12 +- ...UrlRewriteOptions.cs => RewriteOptions.cs} | 6 +- .../RuleAbstraction/RuleTermination.cs | 14 - .../UrlRewrite/Conditions.cs | 14 - .../UrlRewrite/InitialMatch.cs | 14 - .../UrlRewrite/UrlRewriteExtensions.cs | 44 --- .../UrlRewrite/UrlRewriteFileParser.cs | 228 ------------- .../UrlRewrite/UrlRewriteRule.cs | 25 -- .../UrlRewriteExtensions.cs | 67 +++- .../{ => ModRewrite}/ConditionActionTest.cs | 4 +- .../{ => ModRewrite}/FlagParserTest.cs | 4 +- .../ModRewriteConditionBuilderTest.cs | 6 +- .../{ => ModRewrite}/ModRewriteFlagTest.cs | 16 +- .../ModRewriteMiddlewareTest.cs | 46 +-- .../{ => ModRewrite}/RewriteTokenizerTest.cs | 6 +- .../RuleRegexParserTest.cs | 15 +- .../ModRewriteRuleBuilderTest.cs | 14 - .../Rewrite2MiddlewareTests.cs | 92 ----- .../UrlRewrite/FileParserTests.cs | 52 +-- .../UrlRewrite/InputParserTests.cs | 19 +- .../UrlRewrite/MiddleWareTests.cs | 259 ++++++++++++++ 109 files changed, 1295 insertions(+), 770 deletions(-) rename src/Microsoft.AspNetCore.Rewrite/{UrlRewriteOptionsAddRulesExtensions.cs => CodeRewriteExtensions.cs} (77%) rename src/Microsoft.AspNetCore.Rewrite/{RuleAbstraction => Internal}/FunctionalRule.cs (58%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/Condition.cs (91%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/ConditionBuilder.cs (97%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/ConditionExpression.cs (81%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/ConditionFlagType.cs (81%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/ConditionFlags.cs (98%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/ConditionPatternParser.cs (99%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/ConditionTestStringParser.cs (99%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/ConditionType.cs (83%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/ExpressionCreator.cs (97%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/FileParser.cs (97%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/FlagParser.cs (98%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal/ModRewrite}/Operands/IntegerOperand.cs (96%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal/ModRewrite}/Operands/IntegerOperation.cs (82%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal/ModRewrite}/Operands/Operand.cs (85%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal/ModRewrite}/Operands/PropertyOperand.cs (96%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal/ModRewrite}/Operands/PropertyOperation.cs (84%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal/ModRewrite}/Operands/RegexOperand.cs (90%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal/ModRewrite}/Operands/StringOperand.cs (95%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal/ModRewrite}/Operands/StringOperation.cs (81%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/OperationType.cs (88%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/ParsedConditionExpression.cs (92%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/Pattern.cs (95%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/PatternSegment.cs (93%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/RuleBuilder.cs (98%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/RuleFlagType.cs (91%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/RuleFlags.cs (98%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/RuleRegexParser.cs (92%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/SegmentType.cs (100%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/ServerVariables.cs (99%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ModRewrite/Tokenizer.cs (98%) rename src/Microsoft.AspNetCore.Rewrite/{ModRewrite => Internal}/ModRewriteRule.cs (89%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/ParserContext.cs (100%) rename src/Microsoft.AspNetCore.Rewrite/{RuleAbstraction => Internal}/PathRule.cs (76%) rename src/Microsoft.AspNetCore.Rewrite/{RuleAbstraction => Internal}/Rule.cs (63%) rename src/Microsoft.AspNetCore.Rewrite/{RuleAbstraction => Internal}/RuleExpression.cs (73%) create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/RuleResult.cs rename test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteCreatorTest.cs => src/Microsoft.AspNetCore.Rewrite/Internal/RuleTermination.cs (56%) rename src/Microsoft.AspNetCore.Rewrite/{RuleAbstraction => Internal}/SchemeRule.cs (78%) rename src/Microsoft.AspNetCore.Rewrite/{RuleAbstraction => Internal}/Transformation.cs (83%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/ActionType.cs (83%) create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/Condition.cs create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/Conditions.cs rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/InputParser.cs (97%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/LogicalGrouping.cs (81%) create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/MatchResults.cs rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/MatchType.cs (81%) rename src/Microsoft.AspNetCore.Rewrite/{UrlRewrite/Condition.cs => Internal/UrlRewrite/ParsedCondition.cs} (62%) rename src/Microsoft.AspNetCore.Rewrite/{UrlRewrite/UrlAction.cs => Internal/UrlRewrite/ParsedUrlAction.cs} (61%) rename src/Microsoft.AspNetCore.Rewrite/{RuleAbstraction/RuleResult.cs => Internal/UrlRewrite/ParsedUrlMatch.cs} (51%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/Pattern.cs (76%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSegment.cs (76%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSegments/ConditionMatchSegment.cs (72%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSegments/HeaderSegment.cs (80%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSegments/IsHttpsSegment.cs (75%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSegments/LiteralSegment.cs (79%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSegments/LocalAddressSegment.cs (75%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSegments/QueryStringSegment.cs (75%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSegments/RemoteAddressSegment.cs (75%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSegments/RemotePortSegment.cs (77%) create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/RequestFilenameSegment.cs rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSegments/RuleMatchSegment.cs (72%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSegments/ToLowerSegment.cs (82%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSegments/UrlEncodeSegment.cs (83%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSegments/UrlSegment.cs (65%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/PatternSyntax.cs (82%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/RedirectType.cs (84%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/RewriteTags.cs (87%) rename src/Microsoft.AspNetCore.Rewrite/{ => Internal}/UrlRewrite/ServerVariables.cs (90%) create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlAction.cs create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/RedirectAction.cs create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/RedirectClearQueryAction.cs create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/RewriteAction.cs create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/VoidAction.cs create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatch.cs create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/ExactMatch.cs create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/IsDirectoryMatch.cs create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/IsFileMatch.cs create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/RegexMatch.cs create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteFileParser.cs create mode 100644 src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewriteRule.cs rename src/Microsoft.AspNetCore.Rewrite/{ModRewrite => }/ModRewriteExtensions.cs (60%) rename src/Microsoft.AspNetCore.Rewrite/{UrlRewriteContext.cs => RewriteContext.cs} (94%) create mode 100644 src/Microsoft.AspNetCore.Rewrite/RewriteExtensions.cs rename src/Microsoft.AspNetCore.Rewrite/{UrlRewriteMiddleware.cs => RewriteMiddleware.cs} (85%) rename src/Microsoft.AspNetCore.Rewrite/{UrlRewriteOptions.cs => RewriteOptions.cs} (79%) delete mode 100644 src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/RuleTermination.cs delete mode 100644 src/Microsoft.AspNetCore.Rewrite/UrlRewrite/Conditions.cs delete mode 100644 src/Microsoft.AspNetCore.Rewrite/UrlRewrite/InitialMatch.cs delete mode 100644 src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlRewriteExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlRewriteFileParser.cs delete mode 100644 src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlRewriteRule.cs rename test/Microsoft.AspNetCore.Rewrite.Tests/{ => ModRewrite}/ConditionActionTest.cs (97%) rename test/Microsoft.AspNetCore.Rewrite.Tests/{ => ModRewrite}/FlagParserTest.cs (95%) rename test/Microsoft.AspNetCore.Rewrite.Tests/{ => ModRewrite}/ModRewriteConditionBuilderTest.cs (92%) rename test/Microsoft.AspNetCore.Rewrite.Tests/{ => ModRewrite}/ModRewriteFlagTest.cs (84%) rename test/Microsoft.AspNetCore.Rewrite.Tests/{ => ModRewrite}/ModRewriteMiddlewareTest.cs (82%) rename test/Microsoft.AspNetCore.Rewrite.Tests/{ => ModRewrite}/RewriteTokenizerTest.cs (91%) rename test/Microsoft.AspNetCore.Rewrite.Tests/{RuleAbstraction => ModRewrite}/RuleRegexParserTest.cs (69%) delete mode 100644 test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteRuleBuilderTest.cs delete mode 100644 test/Microsoft.AspNetCore.Rewrite.Tests/Rewrite2MiddlewareTests.cs create mode 100644 test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/MiddleWareTests.cs diff --git a/samples/RewriteSample/Startup.cs b/samples/RewriteSample/Startup.cs index f476c62dd5..5fe6a3840c 100644 --- a/samples/RewriteSample/Startup.cs +++ b/samples/RewriteSample/Startup.cs @@ -1,4 +1,8 @@ -using Microsoft.AspNetCore.Builder; +// 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.IO; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Rewrite; @@ -9,7 +13,7 @@ namespace RewriteSample { public void Configure(IApplicationBuilder app, IHostingEnvironment hostingEnv) { - app.UseRewriter(new UrlRewriteOptions() + app.UseRewriter(new RewriteOptions() .ImportFromUrlRewrite(hostingEnv, "UrlRewrite.xml") .ImportFromModRewrite(hostingEnv, "Rewrite.txt")); app.Run(context => context.Response.WriteAsync(context.Request.Path)); @@ -21,6 +25,7 @@ namespace RewriteSample var host = new WebHostBuilder() .UseKestrel() .UseStartup() + .UseContentRoot(Directory.GetCurrentDirectory()) .Build(); host.Run(); diff --git a/samples/RewriteSample/UrlRewrite.xml b/samples/RewriteSample/UrlRewrite.xml index 708ef0e8be..4f5bac7a31 100644 --- a/samples/RewriteSample/UrlRewrite.xml +++ b/samples/RewriteSample/UrlRewrite.xml @@ -1,19 +1,12 @@  - - + + - + + - - - - - - - - - + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewriteOptionsAddRulesExtensions.cs b/src/Microsoft.AspNetCore.Rewrite/CodeRewriteExtensions.cs similarity index 77% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewriteOptionsAddRulesExtensions.cs rename to src/Microsoft.AspNetCore.Rewrite/CodeRewriteExtensions.cs index 9effead54a..51060ebdfc 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewriteOptionsAddRulesExtensions.cs +++ b/src/Microsoft.AspNetCore.Rewrite/CodeRewriteExtensions.cs @@ -4,21 +4,21 @@ using System; using System.Collections.Generic; using System.Text.RegularExpressions; -using Microsoft.AspNetCore.Rewrite.RuleAbstraction; +using Microsoft.AspNetCore.Rewrite.Internal; namespace Microsoft.AspNetCore.Rewrite { /// - /// The builder to a list of rules for and + /// The builder to a list of rules for and /// - public static class UrlRewriteOptionsAddRulesExtensions + public static class CodeRewriteExtensions { /// /// Adds a rule to the current rules. /// /// The UrlRewrite options. /// A rule to be added to the current rules. - public static UrlRewriteOptions AddRule(this UrlRewriteOptions options, Rule rule) + public static RewriteOptions AddRule(this RewriteOptions options, Rule rule) { options.Rules.Add(rule); return options; @@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Rewrite /// /// The UrlRewrite options. /// A list of rules. - public static UrlRewriteOptions AddRules(this UrlRewriteOptions options, List rules) + public static RewriteOptions AddRules(this RewriteOptions options, List rules) { options.Rules.AddRange(rules); return options; @@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Rewrite /// The string to replace the path with (with capture parameters). /// Whether or not to stop rewriting on success of rule. /// - public static UrlRewriteOptions RewritePath(this UrlRewriteOptions options, string regex, string newPath, bool stopRewriteOnSuccess = false) + public static RewriteOptions RewritePath(this RewriteOptions options, string regex, string newPath, bool stopRewriteOnSuccess = false) { options.Rules.Add(new PathRule { MatchPattern = new Regex(regex, RegexOptions.Compiled, TimeSpan.FromMilliseconds(1)), OnMatch = newPath, OnCompletion = stopRewriteOnSuccess ? Transformation.TerminatingRewrite : Transformation.Rewrite }); return options; @@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Rewrite /// The Url rewrite options. /// Whether or not to stop rewriting on success of rule. /// - public static UrlRewriteOptions RewriteScheme(this UrlRewriteOptions options, bool stopRewriteOnSuccess = false) + public static RewriteOptions RewriteScheme(this RewriteOptions options, bool stopRewriteOnSuccess = false) { options.Rules.Add(new SchemeRule {OnCompletion = stopRewriteOnSuccess ? Transformation.TerminatingRewrite : Transformation.Rewrite }); return options; @@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Rewrite /// The string to replace the path with (with capture parameters). /// Whether or not to stop rewriting on success of rule. /// - public static UrlRewriteOptions RedirectPath(this UrlRewriteOptions options, string regex, string newPath, bool stopRewriteOnSuccess = false) + public static RewriteOptions RedirectPath(this RewriteOptions options, string regex, string newPath, bool stopRewriteOnSuccess = false) { options.Rules.Add(new PathRule { MatchPattern = new Regex(regex, RegexOptions.Compiled, TimeSpan.FromMilliseconds(1)), OnMatch = newPath, OnCompletion = Transformation.Redirect }); return options; @@ -81,7 +81,7 @@ namespace Microsoft.AspNetCore.Rewrite /// The Url rewrite options. /// The port to redirect the scheme to. /// - public static UrlRewriteOptions RedirectScheme(this UrlRewriteOptions options, int? sslPort) + public static RewriteOptions RedirectScheme(this RewriteOptions options, int? sslPort) { options.Rules.Add(new SchemeRule { SSLPort = sslPort, OnCompletion = Transformation.Redirect }); return options; @@ -95,7 +95,7 @@ namespace Microsoft.AspNetCore.Rewrite /// /// /// - public static UrlRewriteOptions CustomRule(this UrlRewriteOptions options, Func onApplyRule, Transformation transform, string description = null) + public static RewriteOptions CustomRule(this RewriteOptions options, Func onApplyRule, Transformation transform, string description = null) { options.Rules.Add(new FunctionalRule { OnApplyRule = onApplyRule, OnCompletion = transform}); return options; diff --git a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/FunctionalRule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/FunctionalRule.cs similarity index 58% rename from src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/FunctionalRule.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/FunctionalRule.cs index 073e31945d..5704a23a40 100644 --- a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/FunctionalRule.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/FunctionalRule.cs @@ -3,12 +3,12 @@ using System; -namespace Microsoft.AspNetCore.Rewrite.RuleAbstraction +namespace Microsoft.AspNetCore.Rewrite.Internal { public class FunctionalRule : Rule { - public Func OnApplyRule { get; set; } + public Func OnApplyRule { get; set; } public Transformation OnCompletion { get; set; } = Transformation.Rewrite; - public override RuleResult ApplyRule(UrlRewriteContext context) => OnApplyRule(context); + public override RuleResult ApplyRule(RewriteContext context) => OnApplyRule(context); } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/Condition.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Condition.cs similarity index 91% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/Condition.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Condition.cs index f3940ecaea..e1af53bda7 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/Condition.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Condition.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { public class Condition { diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionBuilder.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionBuilder.cs similarity index 97% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionBuilder.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionBuilder.cs index 109b3b59e1..743b2d8a33 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionBuilder.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionBuilder.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { public class ConditionBuilder { diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionExpression.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionExpression.cs similarity index 81% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionExpression.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionExpression.cs index 85222ba020..4d16a03ede 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionExpression.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionExpression.cs @@ -2,9 +2,9 @@ // 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.Operands; +using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { /// /// Represents the ConditionPattern for a mod_rewrite rule. @@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Rewrite.ModRewrite /// The previous condition results (for backreferences). /// The testString created from the . /// If the testString satisfies the condition - public bool? CheckConditionExpression(UrlRewriteContext context, Match previous, string testString) + public bool? CheckConditionExpression(RewriteContext context, Match previous, string testString) { return Operand.CheckOperation(previous, testString, context.FileProvider) ^ Invert; } diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionFlagType.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionFlagType.cs similarity index 81% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionFlagType.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionFlagType.cs index e1b650e8c0..06c7559090 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionFlagType.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionFlagType.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { public enum ConditionFlagType { diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionFlags.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionFlags.cs similarity index 98% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionFlags.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionFlags.cs index 143e008403..e9687f8dce 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionFlags.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionFlags.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { // TODO Refactor Condition Flags and Rule Flags under base flag class public class ConditionFlags diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionPatternParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionPatternParser.cs similarity index 99% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionPatternParser.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionPatternParser.cs index 24cd7e67c5..2d14d9c7d0 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionPatternParser.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionPatternParser.cs @@ -4,7 +4,7 @@ using System; using Microsoft.AspNetCore.Rewrite.Internal; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { /// /// Parses the "CondPattern" portion of the RewriteCond. diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionTestStringParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionTestStringParser.cs similarity index 99% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionTestStringParser.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionTestStringParser.cs index 04b16b649e..e3f8b1a18e 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionTestStringParser.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionTestStringParser.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using Microsoft.AspNetCore.Rewrite.Internal; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { /// /// Parses the TestString segment of the mod_rewrite condition. diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionType.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionType.cs similarity index 83% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionType.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionType.cs index e30325a8e5..f8f6818979 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ConditionType.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ConditionType.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { public enum ConditionType { diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ExpressionCreator.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ExpressionCreator.cs similarity index 97% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/ExpressionCreator.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ExpressionCreator.cs index 886ccea5a1..0fab8c0d3f 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ExpressionCreator.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ExpressionCreator.cs @@ -3,10 +3,9 @@ using System; using System.Text.RegularExpressions; -using Microsoft.AspNetCore.Rewrite.Operands; -using Microsoft.AspNetCore.Rewrite.RuleAbstraction; +using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { /// /// Converts a parsed expression into a mod_rewrite condition. diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/FileParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/FileParser.cs similarity index 97% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/FileParser.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/FileParser.cs index 201fba8834..3cee0d1e72 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/FileParser.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/FileParser.cs @@ -4,9 +4,9 @@ using System; using System.Collections.Generic; using System.IO; -using Microsoft.AspNetCore.Rewrite.RuleAbstraction; +using Microsoft.AspNetCore.Rewrite.Internal; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { /// /// diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/FlagParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/FlagParser.cs similarity index 98% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/FlagParser.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/FlagParser.cs index b96de6e81a..4053ea8d7e 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/FlagParser.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/FlagParser.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { /// /// Parses the flags diff --git a/src/Microsoft.AspNetCore.Rewrite/Operands/IntegerOperand.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/IntegerOperand.cs similarity index 96% rename from src/Microsoft.AspNetCore.Rewrite/Operands/IntegerOperand.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/IntegerOperand.cs index e65d7bac93..227d1c2bbe 100644 --- a/src/Microsoft.AspNetCore.Rewrite/Operands/IntegerOperand.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/IntegerOperand.cs @@ -6,7 +6,7 @@ using System.Globalization; using System.Text.RegularExpressions; using Microsoft.Extensions.FileProviders; -namespace Microsoft.AspNetCore.Rewrite.Operands +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands { public class IntegerOperand : Operand { diff --git a/src/Microsoft.AspNetCore.Rewrite/Operands/IntegerOperation.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/IntegerOperation.cs similarity index 82% rename from src/Microsoft.AspNetCore.Rewrite/Operands/IntegerOperation.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/IntegerOperation.cs index 3abd0b3e16..873846e123 100644 --- a/src/Microsoft.AspNetCore.Rewrite/Operands/IntegerOperation.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/IntegerOperation.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.Operands +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands { public enum IntegerOperationType { diff --git a/src/Microsoft.AspNetCore.Rewrite/Operands/Operand.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/Operand.cs similarity index 85% rename from src/Microsoft.AspNetCore.Rewrite/Operands/Operand.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/Operand.cs index 0562e14b7c..565cd932fc 100644 --- a/src/Microsoft.AspNetCore.Rewrite/Operands/Operand.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/Operand.cs @@ -4,7 +4,7 @@ using System.Text.RegularExpressions; using Microsoft.Extensions.FileProviders; -namespace Microsoft.AspNetCore.Rewrite.Operands +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands { public abstract class Operand { diff --git a/src/Microsoft.AspNetCore.Rewrite/Operands/PropertyOperand.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/PropertyOperand.cs similarity index 96% rename from src/Microsoft.AspNetCore.Rewrite/Operands/PropertyOperand.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/PropertyOperand.cs index 2637a00119..fd7f649e7d 100644 --- a/src/Microsoft.AspNetCore.Rewrite/Operands/PropertyOperand.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/PropertyOperand.cs @@ -5,7 +5,7 @@ using System; using System.Text.RegularExpressions; using Microsoft.Extensions.FileProviders; -namespace Microsoft.AspNetCore.Rewrite.Operands +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands { public class PropertyOperand : Operand { diff --git a/src/Microsoft.AspNetCore.Rewrite/Operands/PropertyOperation.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/PropertyOperation.cs similarity index 84% rename from src/Microsoft.AspNetCore.Rewrite/Operands/PropertyOperation.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/PropertyOperation.cs index 4fc409e98f..f151c1db64 100644 --- a/src/Microsoft.AspNetCore.Rewrite/Operands/PropertyOperation.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/PropertyOperation.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.Operands +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands { public enum PropertyOperationType { diff --git a/src/Microsoft.AspNetCore.Rewrite/Operands/RegexOperand.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/RegexOperand.cs similarity index 90% rename from src/Microsoft.AspNetCore.Rewrite/Operands/RegexOperand.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/RegexOperand.cs index e9eac3b7bb..e7159b8e43 100644 --- a/src/Microsoft.AspNetCore.Rewrite/Operands/RegexOperand.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/RegexOperand.cs @@ -4,7 +4,7 @@ using System.Text.RegularExpressions; using Microsoft.Extensions.FileProviders; -namespace Microsoft.AspNetCore.Rewrite.Operands +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands { public class RegexOperand : Operand { diff --git a/src/Microsoft.AspNetCore.Rewrite/Operands/StringOperand.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/StringOperand.cs similarity index 95% rename from src/Microsoft.AspNetCore.Rewrite/Operands/StringOperand.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/StringOperand.cs index 06360eb38a..a48b929eff 100644 --- a/src/Microsoft.AspNetCore.Rewrite/Operands/StringOperand.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/StringOperand.cs @@ -5,7 +5,7 @@ using System; using System.Text.RegularExpressions; using Microsoft.Extensions.FileProviders; -namespace Microsoft.AspNetCore.Rewrite.Operands +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands { public class StringOperand : Operand { diff --git a/src/Microsoft.AspNetCore.Rewrite/Operands/StringOperation.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/StringOperation.cs similarity index 81% rename from src/Microsoft.AspNetCore.Rewrite/Operands/StringOperation.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/StringOperation.cs index 51bc4ec48a..a35a51bf9e 100644 --- a/src/Microsoft.AspNetCore.Rewrite/Operands/StringOperation.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Operands/StringOperation.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.Operands +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands { public enum StringOperationType { diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/OperationType.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/OperationType.cs similarity index 88% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/OperationType.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/OperationType.cs index 8f2ec10e9b..4019c1cc11 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/OperationType.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/OperationType.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { public enum OperationType { diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ParsedConditionExpression.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ParsedConditionExpression.cs similarity index 92% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/ParsedConditionExpression.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ParsedConditionExpression.cs index b0402f9e99..5bb69e6e8d 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ParsedConditionExpression.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ParsedConditionExpression.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { public class ParsedModRewriteExpression { diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/Pattern.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Pattern.cs similarity index 95% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/Pattern.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Pattern.cs index 8adcad99dd..8d7de10791 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/Pattern.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Pattern.cs @@ -1,14 +1,12 @@ // 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 System.Text; using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Rewrite.ModRewrite; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { /// /// Contains a sequence of pattern segments, which on obtaining the context, will create the appropriate diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/PatternSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/PatternSegment.cs similarity index 93% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/PatternSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/PatternSegment.cs index 8cb0e961b7..8a59179b5a 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/PatternSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/PatternSegment.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { /// /// A Pattern segment contains a portion of the test string/ substitution segment with a type associated. diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/RuleBuilder.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleBuilder.cs similarity index 98% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/RuleBuilder.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleBuilder.cs index 35530a80bd..9c288b00c3 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/RuleBuilder.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleBuilder.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { public class RuleBuilder { diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/RuleFlagType.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleFlagType.cs similarity index 91% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/RuleFlagType.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleFlagType.cs index d67e698c39..acdb289d2b 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/RuleFlagType.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleFlagType.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { public enum RuleFlagType { diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/RuleFlags.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleFlags.cs similarity index 98% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/RuleFlags.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleFlags.cs index 58496996bd..1c2d632d41 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/RuleFlags.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleFlags.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { public class RuleFlags { diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/RuleRegexParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleRegexParser.cs similarity index 92% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/RuleRegexParser.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleRegexParser.cs index 358eaebc15..3d8254e44d 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/RuleRegexParser.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/RuleRegexParser.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { public static class RuleRegexParser { diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/SegmentType.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/SegmentType.cs similarity index 100% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/SegmentType.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/SegmentType.cs diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ServerVariables.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ServerVariables.cs similarity index 99% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/ServerVariables.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ServerVariables.cs index 421ace308f..ec219142d2 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ServerVariables.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/ServerVariables.cs @@ -9,7 +9,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.Net.Http.Headers; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { /// /// mod_rewrite lookups for specific string constants. diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/Tokenizer.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Tokenizer.cs similarity index 98% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/Tokenizer.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Tokenizer.cs index 9d08094baa..18979e29a0 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/Tokenizer.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewrite/Tokenizer.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using Microsoft.AspNetCore.Rewrite.Internal; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { /// /// Tokenizes a mod_rewrite rule, delimited by spaces. diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ModRewriteRule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewriteRule.cs similarity index 89% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/ModRewriteRule.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ModRewriteRule.cs index 364fbf7275..529ae08eb5 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ModRewriteRule.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/ModRewriteRule.cs @@ -6,9 +6,8 @@ using System.Collections.Generic; using Microsoft.Net.Http.Headers; using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Rewrite.RuleAbstraction; -namespace Microsoft.AspNetCore.Rewrite.ModRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite { public class ModRewriteRule : Rule { @@ -28,7 +27,7 @@ namespace Microsoft.AspNetCore.Rewrite.ModRewrite Description = description; } - public override RuleResult ApplyRule(UrlRewriteContext context) + public override RuleResult ApplyRule(RewriteContext context) { // 1. Figure out which section of the string to match for the initial rule. var results = InitialRule.Operand.RegexOperation.Match(context.HttpContext.Request.Path.ToString()); @@ -36,7 +35,7 @@ namespace Microsoft.AspNetCore.Rewrite.ModRewrite string flagRes = null; if (CheckMatchResult(results.Success)) { - return new RuleResult { Result = RuleTerminiation.Continue }; + return RuleResult.Continue; } if (Flags.HasFlag(RuleFlagType.EscapeBackreference)) @@ -49,7 +48,7 @@ namespace Microsoft.AspNetCore.Rewrite.ModRewrite if (!CheckCondition(context, results, previous)) { - return new RuleResult { Result = RuleTerminiation.Continue }; + return RuleResult.Continue; } // TODO add chained flag @@ -82,12 +81,12 @@ namespace Microsoft.AspNetCore.Rewrite.ModRewrite if (Flags.HasFlag(RuleFlagType.Forbidden)) { context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden; - return new RuleResult { Result = RuleTerminiation.ResponseComplete }; + return RuleResult.ResponseComplete; } else if (Flags.HasFlag(RuleFlagType.Gone)) { context.HttpContext.Response.StatusCode = StatusCodes.Status410Gone; - return new RuleResult { Result = RuleTerminiation.ResponseComplete }; + return RuleResult.ResponseComplete; } else if (result == "-") { @@ -124,7 +123,7 @@ namespace Microsoft.AspNetCore.Rewrite.ModRewrite context.HttpContext.Response.Headers[HeaderNames.Location] = "/" + result + context.HttpContext.Request.QueryString; } } - return new RuleResult { Result = RuleTerminiation.ResponseComplete }; + return RuleResult.ResponseComplete; } else { @@ -145,11 +144,11 @@ namespace Microsoft.AspNetCore.Rewrite.ModRewrite } if (Flags.HasFlag(RuleFlagType.Last) || Flags.HasFlag(RuleFlagType.End)) { - return new RuleResult { Result = RuleTerminiation.StopRules }; + return RuleResult.StopRules; } else { - return new RuleResult { Result = RuleTerminiation.Continue }; + return RuleResult.Continue; } } } @@ -163,7 +162,7 @@ namespace Microsoft.AspNetCore.Rewrite.ModRewrite return !(result.Value ^ InitialRule.Invert); } - private bool CheckCondition(UrlRewriteContext context, Match results, Match previous) + private bool CheckCondition(RewriteContext context, Match results, Match previous) { if (Conditions == null) { diff --git a/src/Microsoft.AspNetCore.Rewrite/ParserContext.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/ParserContext.cs similarity index 100% rename from src/Microsoft.AspNetCore.Rewrite/ParserContext.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/ParserContext.cs diff --git a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/PathRule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/PathRule.cs similarity index 76% rename from src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/PathRule.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/PathRule.cs index 697810ef35..88b07e6cde 100644 --- a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/PathRule.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/PathRule.cs @@ -3,14 +3,14 @@ using System.Text.RegularExpressions; -namespace Microsoft.AspNetCore.Rewrite.RuleAbstraction +namespace Microsoft.AspNetCore.Rewrite.Internal { public class PathRule : Rule { public Regex MatchPattern { get; set; } public string OnMatch { get; set; } public Transformation OnCompletion { get; set; } = Transformation.Rewrite; - public override RuleResult ApplyRule(UrlRewriteContext context) + public override RuleResult ApplyRule(RewriteContext context) { var matches = MatchPattern.Match(context.HttpContext.Request.Path); if (matches.Success) @@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Rewrite.RuleAbstraction path, req.QueryString); context.HttpContext.Response.Redirect(newUrl); - return new RuleResult { Result = RuleTerminiation.ResponseComplete }; + return RuleResult.ResponseComplete; } else { @@ -35,14 +35,14 @@ namespace Microsoft.AspNetCore.Rewrite.RuleAbstraction } if (OnCompletion == Transformation.TerminatingRewrite) { - return new RuleResult { Result = RuleTerminiation.StopRules }; + return RuleResult.StopRules; } else { - return new RuleResult { Result = RuleTerminiation.Continue }; + return RuleResult.Continue; } } - return new RuleResult { Result = RuleTerminiation.Continue }; + return RuleResult.Continue; } } } diff --git a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/Rule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/Rule.cs similarity index 63% rename from src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/Rule.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/Rule.cs index 0b636120d2..3ba6067f42 100644 --- a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/Rule.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/Rule.cs @@ -1,11 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.RuleAbstraction +namespace Microsoft.AspNetCore.Rewrite.Internal { public abstract class Rule { - public abstract RuleResult ApplyRule(UrlRewriteContext context); + public abstract RuleResult ApplyRule(RewriteContext context); } } diff --git a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/RuleExpression.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/RuleExpression.cs similarity index 73% rename from src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/RuleExpression.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/RuleExpression.cs index e14728e33c..52458cc542 100644 --- a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/RuleExpression.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/RuleExpression.cs @@ -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. -using Microsoft.AspNetCore.Rewrite.Operands; +using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands; -namespace Microsoft.AspNetCore.Rewrite.RuleAbstraction +namespace Microsoft.AspNetCore.Rewrite.Internal { public class RuleExpression { diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/RuleResult.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/RuleResult.cs new file mode 100644 index 0000000000..f7b6c2b45b --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/RuleResult.cs @@ -0,0 +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 +{ + 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 RuleTerminiation Result { get; set; } + } +} diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteCreatorTest.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/RuleTermination.cs similarity index 56% rename from test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteCreatorTest.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/RuleTermination.cs index c9a9dd21a1..449a422944 100644 --- a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteCreatorTest.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/RuleTermination.cs @@ -1,9 +1,12 @@ // 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 +namespace Microsoft.AspNetCore.Rewrite.Internal { - public class ModRewriteCreatorTest + public enum RuleTerminiation { + Continue, + ResponseComplete, + StopRules } } diff --git a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/SchemeRule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/SchemeRule.cs similarity index 78% rename from src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/SchemeRule.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/SchemeRule.cs index 427a38bfc6..87a08544e8 100644 --- a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/SchemeRule.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/SchemeRule.cs @@ -4,13 +4,13 @@ using System.Text; using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNetCore.Rewrite.RuleAbstraction +namespace Microsoft.AspNetCore.Rewrite.Internal { public class SchemeRule : Rule { public int? SSLPort { get; set; } public Transformation OnCompletion { get; set; } = Transformation.Rewrite; - public override RuleResult ApplyRule(UrlRewriteContext context) + public override RuleResult ApplyRule(RewriteContext context) { // TODO this only does http to https, add more features in the future. @@ -34,11 +34,11 @@ namespace Microsoft.AspNetCore.Rewrite.RuleAbstraction context.HttpContext.Request.Host = host; if (OnCompletion == Transformation.TerminatingRewrite) { - return new RuleResult { Result = RuleTerminiation.StopRules }; + return RuleResult.StopRules; } else { - return new RuleResult { Result = RuleTerminiation.Continue }; + return RuleResult.Continue; } } @@ -46,9 +46,9 @@ namespace Microsoft.AspNetCore.Rewrite.RuleAbstraction var newUrl = new StringBuilder().Append("https://").Append(host).Append(req.PathBase).Append(req.Path).Append(req.QueryString); context.HttpContext.Response.Redirect(newUrl.ToString()); - return new RuleResult { Result = RuleTerminiation.ResponseComplete }; + return RuleResult.ResponseComplete; } - return new RuleResult { Result = RuleTerminiation.Continue }; ; + return RuleResult.Continue; } } } diff --git a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/Transformation.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/Transformation.cs similarity index 83% rename from src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/Transformation.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/Transformation.cs index 44008b89a4..01ca2dc9cf 100644 --- a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/Transformation.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/Transformation.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.RuleAbstraction +namespace Microsoft.AspNetCore.Rewrite.Internal { public enum Transformation { diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/ActionType.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ActionType.cs similarity index 83% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/ActionType.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ActionType.cs index a7eff7669d..877871073b 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/ActionType.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ActionType.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite { public enum ActionType { diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/Condition.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/Condition.cs new file mode 100644 index 0000000000..f6541d48f9 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/Condition.cs @@ -0,0 +1,16 @@ +// 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.UrlRewrite +{ + public class Condition + { + public Pattern Input { get; set; } + public UrlMatch Match { get; set; } + public MatchResults Evaluate(RewriteContext context, MatchResults ruleMatch, MatchResults condMatch) + { + var pattern = Input.Evaluate(context.HttpContext, ruleMatch, condMatch); + return Match.Evaluate(pattern, context); + } + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/Conditions.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/Conditions.cs new file mode 100644 index 0000000000..b9ffa5b26c --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/Conditions.cs @@ -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 System.Collections.Generic; + +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite +{ + public class Conditions + { + public List ConditionList { get; set; } = new List(); + public LogicalGrouping MatchType { get; set; } // default is MatchAll + public bool TrackingAllCaptures { get; set; } + + public MatchResults Evaluate(RewriteContext context, MatchResults ruleMatch) + { + MatchResults prevCond = null; + var success = true; + foreach (var condition in ConditionList) + { + var res = condition.Evaluate(context, ruleMatch, prevCond); + success = (MatchType == LogicalGrouping.MatchAll ? (success && res.Success) : (success || res.Success)); + prevCond = res; + } + return new MatchResults { Success = success, BackReference = prevCond?.BackReference }; + } + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/InputParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/InputParser.cs similarity index 97% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/InputParser.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/InputParser.cs index eb8bbd0410..8d45ac0433 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/InputParser.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/InputParser.cs @@ -3,11 +3,9 @@ using System; using System.Collections.Generic; -using System.Text.Encodings.Web; -using Microsoft.AspNetCore.Rewrite.Internal; -using Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments; +using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite { /// /// diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/LogicalGrouping.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/LogicalGrouping.cs similarity index 81% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/LogicalGrouping.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/LogicalGrouping.cs index 5f2568c8e6..275d317b65 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/LogicalGrouping.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/LogicalGrouping.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite { public enum LogicalGrouping { diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/MatchResults.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/MatchResults.cs new file mode 100644 index 0000000000..6f182109f8 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/MatchResults.cs @@ -0,0 +1,13 @@ +// 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; + +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite +{ + public class MatchResults + { + public GroupCollection BackReference { get; set; } + public bool Success { get; set; } + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/MatchType.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/MatchType.cs similarity index 81% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/MatchType.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/MatchType.cs index 260ecba3d0..cfb763dcfb 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/MatchType.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/MatchType.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite { public enum MatchType { diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/Condition.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedCondition.cs similarity index 62% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/Condition.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedCondition.cs index 17030d2d5f..e34ccdb00f 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/Condition.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedCondition.cs @@ -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 System.Text.RegularExpressions; - -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite { - public class Condition + public class ParsedCondition { - public Pattern Input { get; set; } - public Regex MatchPattern { get; set; } public bool Negate { get; set; } public bool IgnoreCase { get; set; } = true; public MatchType MatchType { get; set; } = MatchType.Pattern; diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedUrlAction.cs similarity index 61% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlAction.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedUrlAction.cs index c0d56f603a..857c2f16cd 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlAction.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedUrlAction.cs @@ -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.UrlRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite { - public class UrlAction + public class ParsedUrlAction { public ActionType Type { get; set; } public Pattern Url { get; set; } - public bool AppendQueryString { get; set; } - public bool LogRewrittenUrl { get; set; } + public bool AppendQueryString { get; set; } = true; + public bool LogRewrittenUrl { get; set; } // Ignoring this flag. public RedirectType RedirectType { get; set; } = RedirectType.Permanent; } } diff --git a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/RuleResult.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedUrlMatch.cs similarity index 51% rename from src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/RuleResult.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedUrlMatch.cs index 67aa51f583..9f183fadc3 100644 --- a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/RuleResult.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ParsedUrlMatch.cs @@ -1,10 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.RuleAbstraction +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite { - public class RuleResult + public class ParsedUrlMatch { - public RuleTerminiation Result { get; set; } + public bool IgnoreCase { get; set; } + public bool Negate { get; set; } } } diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/Pattern.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/Pattern.cs similarity index 76% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/Pattern.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/Pattern.cs index aa62e3c825..a796da468f 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/Pattern.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/Pattern.cs @@ -3,23 +3,23 @@ using System.Collections.Generic; using System.Text; -using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite { public class Pattern { public IList PatternSegments { get; } - public Pattern(List patternSegments) { PatternSegments = patternSegments; } - public string Evaluate(HttpContext context, Match ruleMatch, Match condMatch) + public string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) { var strBuilder = new StringBuilder(); + + // TODO consider thread static for string builder - DAVID PERF foreach (var pattern in PatternSegments) { strBuilder.Append(pattern.Evaluate(context, ruleMatch, condMatch)); diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegment.cs similarity index 76% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegment.cs index d80755d77a..820d5cdfb4 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegment.cs @@ -1,15 +1,13 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; -using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite { public abstract class PatternSegment { // Match from prevRule, Match from prevCond - public abstract string Evaluate(HttpContext context, Match ruleMatch, Match condMatch); + public abstract string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch); } } diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/ConditionMatchSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/ConditionMatchSegment.cs similarity index 72% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/ConditionMatchSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/ConditionMatchSegment.cs index ec53c1549a..1c65243e16 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/ConditionMatchSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/ConditionMatchSegment.cs @@ -1,10 +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. -using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments { public class ConditionMatchSegment : PatternSegment { @@ -15,9 +14,9 @@ namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments Index = index; } - public override string Evaluate(HttpContext context, Match ruleMatch, Match condMatch) + public override string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) { - return condMatch?.Groups[Index]?.Value; + return condMatch?.BackReference[Index]?.Value; } } } diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/HeaderSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/HeaderSegment.cs similarity index 80% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/HeaderSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/HeaderSegment.cs index 0353598bea..c83b2cf6ad 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/HeaderSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/HeaderSegment.cs @@ -1,10 +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. -using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments { public class HeaderSegment : PatternSegment { @@ -15,7 +14,7 @@ namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments Header = header; } - public override string Evaluate(HttpContext context, Match ruleMatch, Match condMatch) + public override string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) { return context.Request.Headers[Header]; } diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/IsHttpsSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/IsHttpsSegment.cs similarity index 75% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/IsHttpsSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/IsHttpsSegment.cs index ff6be8e823..5ffece8e11 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/IsHttpsSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/IsHttpsSegment.cs @@ -1,14 +1,13 @@ // 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.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments { public class IsHttpsSegment : PatternSegment { - public override string Evaluate(HttpContext context, Match ruleMatch, Match condMatch) + public override string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) { return context.Request.IsHttps ? "ON" : "OFF"; } diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/LiteralSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/LiteralSegment.cs similarity index 79% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/LiteralSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/LiteralSegment.cs index 43b45fec9c..390459c6c8 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/LiteralSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/LiteralSegment.cs @@ -1,10 +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. -using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments { public class LiteralSegment : PatternSegment { @@ -15,7 +14,7 @@ namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments Literal = literal; } - public override string Evaluate(HttpContext context, Match ruleMatch, Match condMatch) + public override string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) { return Literal; } diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/LocalAddressSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/LocalAddressSegment.cs similarity index 75% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/LocalAddressSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/LocalAddressSegment.cs index a26e79238b..10d77aeb02 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/LocalAddressSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/LocalAddressSegment.cs @@ -1,14 +1,13 @@ // 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.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments { public class LocalAddressSegment : PatternSegment { - public override string Evaluate(HttpContext context, Match ruleMatch, Match condMatch) + public override string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) { return context.Connection.LocalIpAddress?.ToString(); } diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/QueryStringSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/QueryStringSegment.cs similarity index 75% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/QueryStringSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/QueryStringSegment.cs index 5b51d8f98c..d5081a4e6a 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/QueryStringSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/QueryStringSegment.cs @@ -1,14 +1,13 @@ // 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.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments { public class QueryStringSegment : PatternSegment { - public override string Evaluate(HttpContext context, Match ruleMatch, Match condMatch) + public override string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) { return context.Request.QueryString.ToString(); } diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/RemoteAddressSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/RemoteAddressSegment.cs similarity index 75% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/RemoteAddressSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/RemoteAddressSegment.cs index 20bf50c523..499b5a3e91 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/RemoteAddressSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/RemoteAddressSegment.cs @@ -1,14 +1,13 @@ // 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.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments { public class RemoteAddressSegment : PatternSegment { - public override string Evaluate(HttpContext context, Match ruleMatch, Match condMatch) + public override string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) { return context.Connection.RemoteIpAddress?.ToString(); } diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/RemotePortSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/RemotePortSegment.cs similarity index 77% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/RemotePortSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/RemotePortSegment.cs index bb1c391b29..25456dc102 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/RemotePortSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/RemotePortSegment.cs @@ -2,14 +2,13 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Globalization; -using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments { public class RemotePortSegment : PatternSegment { - public override string Evaluate(HttpContext context, Match ruleMatch, Match condMatch) + public override string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) { return context.Connection.RemotePort.ToString(CultureInfo.InvariantCulture); } diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/RequestFilenameSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/RequestFilenameSegment.cs new file mode 100644 index 0000000000..8d467684f6 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/RequestFilenameSegment.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments +{ + public class RequestFileNameSegment : PatternSegment + { + public override string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) + { + return context.Request.Path; + } + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/RuleMatchSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/RuleMatchSegment.cs similarity index 72% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/RuleMatchSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/RuleMatchSegment.cs index 2ebbb0f61c..b8384aaa49 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/RuleMatchSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/RuleMatchSegment.cs @@ -1,10 +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. -using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments { public class RuleMatchSegment : PatternSegment { @@ -15,9 +14,9 @@ namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments Index = index; } - public override string Evaluate(HttpContext context, Match ruleMatch, Match condMatch) + public override string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) { - return ruleMatch?.Groups[Index]?.Value; + return ruleMatch?.BackReference[Index]?.Value; } } } diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/ToLowerSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/ToLowerSegment.cs similarity index 82% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/ToLowerSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/ToLowerSegment.cs index 945bdd19f8..b2c9d85679 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/ToLowerSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/ToLowerSegment.cs @@ -1,10 +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. -using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments { public class ToLowerSegment : PatternSegment { @@ -15,7 +14,7 @@ namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments Pattern = pattern; } - public override string Evaluate(HttpContext context, Match ruleMatch, Match condMatch) + public override string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) { var pattern = Pattern.Evaluate(context, ruleMatch, condMatch); return pattern.ToLowerInvariant(); diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/UrlEncodeSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/UrlEncodeSegment.cs similarity index 83% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/UrlEncodeSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/UrlEncodeSegment.cs index 4f97346a8d..83edb5019c 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/UrlEncodeSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/UrlEncodeSegment.cs @@ -2,10 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Text.Encodings.Web; -using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments { public class UrlEncodeSegment : PatternSegment { @@ -16,7 +15,7 @@ namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments Pattern = pattern; } - public override string Evaluate(HttpContext context, Match ruleMatch, Match condMatch) + public override string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) { var pattern = Pattern.Evaluate(context, ruleMatch, condMatch); return UrlEncoder.Default.Encode(pattern); diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/UrlSegment.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/UrlSegment.cs similarity index 65% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/UrlSegment.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/UrlSegment.cs index 9dc24ec930..dca3bfb5de 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSegments/UrlSegment.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSegments/UrlSegment.cs @@ -1,16 +1,15 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments { public class UrlSegment : PatternSegment { - public override string Evaluate(HttpContext context, Match ruleMatch, Match condMatch) + public override string Evaluate(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) { - return context.Request.Path.ToString(); + return context.Request.Path; } } } diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSyntax.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSyntax.cs similarity index 82% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSyntax.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSyntax.cs index efdf403427..c32b04f844 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/PatternSyntax.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/PatternSyntax.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite { public enum PatternSyntax { diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/RedirectType.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/RedirectType.cs similarity index 84% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/RedirectType.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/RedirectType.cs index 5d842c57d4..ce52d9d408 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/RedirectType.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/RedirectType.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite { public enum RedirectType { diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/RewriteTags.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/RewriteTags.cs similarity index 87% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/RewriteTags.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/RewriteTags.cs index 5e4d23242d..16074abfb3 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/RewriteTags.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/RewriteTags.cs @@ -1,11 +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. -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite { public static class RewriteTags { - // TODO More strings to be added later once further implementations are added. public const string Rewrite = "rewrite"; public const string GlobalRules = "globalRules"; public const string Rules = "rules"; @@ -27,7 +26,7 @@ namespace Microsoft.AspNetCore.Rewrite.UrlRewrite public const string Input = "input"; public const string Pattern = "pattern"; public const string Type = "type"; - public const string AppendQuery = "appendQuery"; + public const string AppendQuery = "appendQueryString"; public const string LogRewrittenUrl = "logRewrittenUrl"; public const string RedirectType = "redirectType"; } diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/ServerVariables.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ServerVariables.cs similarity index 90% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewrite/ServerVariables.cs rename to src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ServerVariables.cs index 7ffb9a5da4..2b0fcad556 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/ServerVariables.cs +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/ServerVariables.cs @@ -2,16 +2,13 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Globalization; -using System.Text.RegularExpressions; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Rewrite.UrlRewrite.PatternSegments; +using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.PatternSegments; using Microsoft.Net.Http.Headers; -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite { public static class ServerVariables - { + { public static PatternSegment FindServerVariable(string serverVariable) { switch(serverVariable) @@ -53,6 +50,8 @@ namespace Microsoft.AspNetCore.Rewrite.UrlRewrite throw new NotImplementedException(); case "REMOTE_PORT": return new RemotePortSegment(); + case "REQUEST_FILENAME": + return new RequestFileNameSegment(); default: throw new FormatException("Unrecognized server variable."); } diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlAction.cs new file mode 100644 index 0000000000..404561b25b --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlAction.cs @@ -0,0 +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. + +using Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite +{ + public abstract class UrlAction + { + public Pattern Url { get; set; } + + public abstract RuleResult ApplyAction(HttpContext context, MatchResults ruleMatch, MatchResults condMatch); + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/RedirectAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/RedirectAction.cs new file mode 100644 index 0000000000..a990c346dc --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/RedirectAction.cs @@ -0,0 +1,42 @@ +// 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.Net.Http.Headers; + +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlActions +{ + public class RedirectAction : UrlAction + { + public int StatusCode { get; } + public RedirectAction(int statusCode, Pattern pattern) + { + StatusCode = statusCode; + Url = pattern; + } + + public override RuleResult ApplyAction(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) + { + + var pattern = Url.Evaluate(context, ruleMatch, condMatch); + context.Response.StatusCode = StatusCode; + + // 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) + { + var query = context.Request.QueryString.Add(new QueryString(pattern.Substring(split))); + // not using the response.redirect here because status codes may be 301, 302, 307, 308 + context.Response.Headers[HeaderNames.Location] = pattern.Substring(0, split) + query; + } + else + { + context.Response.Headers[HeaderNames.Location] = pattern; + } + return RuleResult.ResponseComplete; + } + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/RedirectClearQueryAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/RedirectClearQueryAction.cs new file mode 100644 index 0000000000..a6439811c5 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/RedirectClearQueryAction.cs @@ -0,0 +1,29 @@ +// 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.Net.Http.Headers; + +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlActions +{ + public class RedirectClearQueryAction : UrlAction + { + public int StatusCode { get; } + public RedirectClearQueryAction(int statusCode, Pattern pattern) + { + StatusCode = statusCode; + Url = pattern; + } + + public override RuleResult ApplyAction(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) + { + var pattern = Url.Evaluate(context, ruleMatch, condMatch); + context.Response.StatusCode = StatusCode; + + // we are clearing the query, so just put the pattern in the location header + context.Response.Headers[HeaderNames.Location] = pattern; + return RuleResult.ResponseComplete; + } + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/RewriteAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/RewriteAction.cs new file mode 100644 index 0000000000..9c7c463b82 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/RewriteAction.cs @@ -0,0 +1,60 @@ +// 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.Extensions; + +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlActions +{ + public class RewriteAction : UrlAction + { + public RuleTerminiation Result { get; } + public bool ClearQuery { get; } + + public RewriteAction(RuleTerminiation result, Pattern pattern, bool clearQuery) + { + Result = result; + Url = pattern; + ClearQuery = clearQuery; + } + + public override RuleResult ApplyAction(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) + { + var pattern = Url.Evaluate(context, ruleMatch, condMatch); + + if (ClearQuery) + { + context.Request.QueryString = new QueryString(); + } + // TODO PERF, substrings, object creation, etc. + if (pattern.IndexOf("://") >= 0) + { + string scheme = null; + var host = new HostString(); + var path = new PathString(); + var query = new QueryString(); + var fragment = new FragmentString(); + UriHelper.FromAbsolute(pattern, out scheme, out host, out path, out query, out fragment); + + context.Request.Scheme = scheme; + context.Request.Host = host; + context.Request.Path = path; + context.Request.QueryString = query.Add(context.Request.QueryString); + } + else + { + var split = pattern.IndexOf('?'); + if (split >= 0) + { + context.Request.Path = new PathString("/" + pattern.Substring(0, split)); + context.Request.QueryString = context.Request.QueryString.Add(new QueryString(pattern.Substring(split))); + } + else + { + context.Request.Path = new PathString("/" + pattern); + } + } + return new RuleResult { Result = Result }; + } + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/VoidAction.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/VoidAction.cs new file mode 100644 index 0000000000..5098a06ee6 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlActions/VoidAction.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Rewrite.Internal; + +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlActions +{ + public class VoidAction : UrlAction + { + // Explicitly say that nothing happens + public override RuleResult ApplyAction(HttpContext context, MatchResults ruleMatch, MatchResults condMatch) + { + return RuleResult.Continue; + } + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatch.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatch.cs new file mode 100644 index 0000000000..5cd97d9c94 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatch.cs @@ -0,0 +1,11 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite +{ + public abstract class UrlMatch + { + public bool Negate { get; set; } + public abstract MatchResults Evaluate(string input, RewriteContext context); + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/ExactMatch.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/ExactMatch.cs new file mode 100644 index 0000000000..a42fe3e6a1 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/ExactMatch.cs @@ -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. + +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlMatches +{ + public class ExactMatch : UrlMatch + { + public bool IgnoreCase { get; } + public string StringMatch { get; } + + public ExactMatch(bool ignoreCase, string input, bool negate) + { + IgnoreCase = ignoreCase; + StringMatch = input; + Negate = negate; + } + + public override MatchResults Evaluate(string pattern, RewriteContext context) + { + var pathMatch = string.Compare(pattern, StringMatch, IgnoreCase); + return new MatchResults { Success = ((pathMatch == 0) != Negate) }; + } + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/IsDirectoryMatch.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/IsDirectoryMatch.cs new file mode 100644 index 0000000000..9c1068ada0 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/IsDirectoryMatch.cs @@ -0,0 +1,19 @@ +// 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.UrlRewrite.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; + return new MatchResults { Success = (res != Negate) }; + } + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/IsFileMatch.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/IsFileMatch.cs new file mode 100644 index 0000000000..ebce79b655 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/IsFileMatch.cs @@ -0,0 +1,19 @@ +// 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.UrlRewrite.UrlMatches +{ + public class IsFileMatch : UrlMatch + { + public IsFileMatch(bool negate) + { + Negate = negate; + } + + public override MatchResults Evaluate(string pattern, RewriteContext context) + { + var res = context.FileProvider.GetFileInfo(pattern).Exists; + return new MatchResults { Success = (res != Negate) }; + } + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/RegexMatch.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/RegexMatch.cs new file mode 100644 index 0000000000..a1859a9370 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlMatches/RegexMatch.cs @@ -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 System; +using System.Text.RegularExpressions; + +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlMatches +{ + public class RegexMatch : UrlMatch + { + private static readonly TimeSpan RegexTimeout = TimeSpan.FromMilliseconds(1); + + public Regex Match { get; } + + public RegexMatch(Regex match, bool negate) + { + Match = match; + Negate = negate; + } + + public override MatchResults Evaluate(string pattern, RewriteContext context) + { + var res = Match.Match(pattern); + return new MatchResults { BackReference = res.Groups, Success = (res.Success != Negate)}; + } + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteFileParser.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteFileParser.cs new file mode 100644 index 0000000000..289d9567e9 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewrite/UrlRewriteFileParser.cs @@ -0,0 +1,316 @@ +// 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 System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Xml.Linq; +using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlActions; +using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlMatches; + +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite +{ + public static class UrlRewriteFileParser + { + private static readonly TimeSpan RegexTimeout = TimeSpan.FromMilliseconds(1); + + public static List Parse(TextReader reader) + { + var temp = XDocument.Load(reader); + var xmlRoot = temp.Descendants(RewriteTags.Rewrite).FirstOrDefault(); + + if (xmlRoot != null) + { + var result = new List(); + // TODO Global rules are currently not treated differently than normal rules, fix. + // See: https://github.com/aspnet/BasicMiddleware/issues/59 + ParseRules(xmlRoot.Descendants(RewriteTags.GlobalRules).FirstOrDefault(), result, isGlobalRule: true); + ParseRules(xmlRoot.Descendants(RewriteTags.Rules).FirstOrDefault(), result, isGlobalRule: false); + return result; + } + return null; + } + + private static void ParseRules(XElement rules, List result, bool isGlobalRule) + { + if (rules == null) + { + return; + } + + foreach (var rule in rules.Elements(RewriteTags.Rule)) + { + var res = new UrlRewriteRule(); + SetRuleAttributes(rule, res); + CreateUrlAction(rule.Element(RewriteTags.Action), res, isGlobalRule); + if (res.Enabled) + { + result.Add(res); + } + } + } + + private static void SetRuleAttributes(XElement rule, UrlRewriteRule res) + { + + res.Name = rule.Attribute(RewriteTags.Name)?.Value; + + bool enabled; + if (bool.TryParse(rule.Attribute(RewriteTags.Enabled)?.Value, out enabled)) + { + res.Enabled = enabled; + } + + PatternSyntax patternSyntax; + if (Enum.TryParse(rule.Attribute(RewriteTags.PatternSyntax)?.Value, out patternSyntax)) + { + res.PatternSyntax = patternSyntax; + } + + bool stopProcessing; + if (bool.TryParse(rule.Attribute(RewriteTags.StopProcessing)?.Value, out stopProcessing)) + { + res.StopProcessing = stopProcessing; + } + + CreateMatch(rule.Element(RewriteTags.Match), res); + CreateConditions(rule.Element(RewriteTags.Conditions), res); + } + + private static void CreateMatch(XElement match, UrlRewriteRule res) + { + if (match == null) + { + throw new FormatException("Rules must have an associated match."); + } + + var matchRes = new ParsedUrlMatch(); + + bool parBool; + if (bool.TryParse(match.Attribute(RewriteTags.IgnoreCase)?.Value, out parBool)) + { + matchRes.IgnoreCase = parBool; + } + + if (bool.TryParse(match.Attribute(RewriteTags.Negate)?.Value, out parBool)) + { + matchRes.Negate = parBool; + } + + var parsedInputString = match.Attribute(RewriteTags.Url)?.Value; + + switch (res.PatternSyntax) + { + case PatternSyntax.ECMAScript: + { + if (matchRes.IgnoreCase) + { + var regex = new Regex(parsedInputString, RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout); + res.InitialMatch = new RegexMatch(regex, matchRes.Negate); + } + else + { + var regex = new Regex(parsedInputString, RegexOptions.Compiled, RegexTimeout); + res.InitialMatch = new RegexMatch(regex, matchRes.Negate); + } + } + break; + case PatternSyntax.WildCard: + throw new NotImplementedException("Wildcard syntax is not supported."); + case PatternSyntax.ExactMatch: + res.InitialMatch = new ExactMatch(matchRes.IgnoreCase, parsedInputString, matchRes.Negate); + break; + } + } + + + private static void CreateConditions(XElement conditions, UrlRewriteRule res) + { + // This is to avoid nullptr exception on referencing conditions. + res.Conditions = new Conditions(); + if (conditions == null) + { + return; + } + + LogicalGrouping grouping; + if (Enum.TryParse(conditions.Attribute(RewriteTags.MatchType)?.Value, out grouping)) + { + res.Conditions.MatchType = grouping; + } + + bool parBool; + if (bool.TryParse(conditions.Attribute(RewriteTags.TrackingAllCaptures)?.Value, out parBool)) + { + res.Conditions.TrackingAllCaptures = parBool; + } + + foreach (var cond in conditions.Elements(RewriteTags.Add)) + { + CreateCondition(cond, res); + } + } + + private static void CreateCondition(XElement condition, UrlRewriteRule res) + { + + var parsedCondRes = new ParsedCondition(); + + bool parBool; + if (bool.TryParse(condition.Attribute(RewriteTags.IgnoreCase)?.Value, out parBool)) + { + parsedCondRes.IgnoreCase = parBool; + } + + if (bool.TryParse(condition.Attribute(RewriteTags.Negate)?.Value, out parBool)) + { + parsedCondRes.Negate = parBool; + } + + MatchType matchType; + if (Enum.TryParse(condition.Attribute(RewriteTags.MatchType)?.Value, out matchType)) + { + parsedCondRes.MatchType = matchType; + } + + var parsedString = condition.Attribute(RewriteTags.Input)?.Value; + if (parsedString == null) + { + throw new FormatException("Null input for condition"); + } + + var input = InputParser.ParseInputString(parsedString); + + switch (res.PatternSyntax) + { + case PatternSyntax.ECMAScript: + { + switch (parsedCondRes.MatchType) + { + case MatchType.Pattern: + { + parsedString = condition.Attribute(RewriteTags.Pattern)?.Value; + if (parsedString == null) + { + throw new FormatException("Pattern match does not have an associated pattern attribute in condition."); + } + Regex regex = null; + + if (parsedCondRes.IgnoreCase) + { + regex = new Regex(parsedString, RegexOptions.Compiled | RegexOptions.IgnoreCase, RegexTimeout); + } + else + { + regex = new Regex(parsedString, RegexOptions.Compiled, RegexTimeout); + } + + res.Conditions.ConditionList.Add(new Condition { Input = input, Match = new RegexMatch(regex, parsedCondRes.Negate) }); + } + break; + case MatchType.IsDirectory: + { + res.Conditions.ConditionList.Add(new Condition { Input = input, Match = new IsDirectoryMatch(parsedCondRes.Negate) }); + } + break; + case MatchType.IsFile: + { + res.Conditions.ConditionList.Add(new Condition { Input = input, Match = new IsFileMatch(parsedCondRes.Negate) }); + } + break; + default: + throw new FormatException("Unrecognized matchType."); + } + + } + break; + case PatternSyntax.WildCard: + throw new NotImplementedException("Wildcard syntax is not supported."); + case PatternSyntax.ExactMatch: + parsedString = condition.Attribute(RewriteTags.Pattern)?.Value; + if (parsedString == null) + { + throw new FormatException("Pattern match does not have an associated pattern attribute in condition."); + } + res.Conditions.ConditionList.Add(new Condition { Input = input, Match = new ExactMatch(parsedCondRes.IgnoreCase, parsedString, parsedCondRes.Negate) }); + break; + default: + throw new FormatException("Unrecognized pattern syntax."); + } + } + + private static void CreateUrlAction(XElement urlAction, UrlRewriteRule res, bool globalRule) + { + if (urlAction == null) + { + throw new FormatException("Action is a required element of a rule."); + } + + var actionRes = new ParsedUrlAction(); + + ActionType actionType; + if (Enum.TryParse(urlAction.Attribute(RewriteTags.Type)?.Value, out actionType)) + { + actionRes.Type = actionType; + } + + bool parseBool; + if (bool.TryParse(urlAction.Attribute(RewriteTags.AppendQuery)?.Value, out parseBool)) + { + actionRes.AppendQueryString = parseBool; + } + + if (bool.TryParse(urlAction.Attribute(RewriteTags.LogRewrittenUrl)?.Value, out parseBool)) + { + actionRes.LogRewrittenUrl = parseBool; + } + + RedirectType redirectType; + if (Enum.TryParse(urlAction.Attribute(RewriteTags.RedirectType)?.Value, out redirectType)) + { + actionRes.RedirectType = redirectType; + } + + actionRes.Url = InputParser.ParseInputString(urlAction.Attribute(RewriteTags.Url)?.Value); + + CreateUrlActionFromParsedAction(actionRes, globalRule, res); + } + + public static void CreateUrlActionFromParsedAction(ParsedUrlAction actionRes, bool globalRule, UrlRewriteRule res) + { + switch (actionRes.Type) + { + case ActionType.None: + res.Action = new VoidAction(); + break; + case ActionType.Rewrite: + if (actionRes.AppendQueryString) + { + res.Action = new RewriteAction(res.StopProcessing ? RuleTerminiation.StopRules : RuleTerminiation.Continue, actionRes.Url, clearQuery: false); + } + else + { + res.Action = new RewriteAction(res.StopProcessing ? RuleTerminiation.StopRules : RuleTerminiation.Continue, actionRes.Url, clearQuery: true); + } + break; + case ActionType.Redirect: + if (actionRes.AppendQueryString) + { + res.Action = new RedirectAction((int)actionRes.RedirectType, actionRes.Url); + } + else + { + res.Action = new RedirectClearQueryAction((int)actionRes.RedirectType, actionRes.Url); + } + break; + case ActionType.AbortRequest: + throw new FormatException("Abort requests are not supported."); + case ActionType.CustomResponse: + // TODO + throw new FormatException("Custom Responses are not supported"); + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewriteRule.cs b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewriteRule.cs new file mode 100644 index 0000000000..9bd9c7e155 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/Internal/UrlRewriteRule.cs @@ -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. + +namespace Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite +{ + public class UrlRewriteRule : Rule + { + public string Name { get; set; } + public bool Enabled { get; set; } = true; + public PatternSyntax PatternSyntax { get; set; } + public bool StopProcessing { get; set; } + public UrlMatch InitialMatch { get; set; } + public Conditions Conditions { get; set; } + public UrlAction Action { get; set; } + + 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 + var initMatchRes = InitialMatch.Evaluate(context.HttpContext.Request.Path.ToString().Substring(1), context); + + if (!initMatchRes.Success) + { + return RuleResult.Continue; + } + + var condMatchRes = Conditions.Evaluate(context, initMatchRes); + if (!condMatchRes.Success) + { + return RuleResult.Continue; + } + + // at this point we know the rule passed, evaluate the replacement. + return Action.ApplyAction(context.HttpContext, initMatchRes, condMatchRes); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Rewrite/Microsoft.AspNetCore.Rewrite.xproj b/src/Microsoft.AspNetCore.Rewrite/Microsoft.AspNetCore.Rewrite.xproj index fbaad5c7ae..08f543fc53 100644 --- a/src/Microsoft.AspNetCore.Rewrite/Microsoft.AspNetCore.Rewrite.xproj +++ b/src/Microsoft.AspNetCore.Rewrite/Microsoft.AspNetCore.Rewrite.xproj @@ -5,7 +5,7 @@ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - + 0e7ca1a7-1dc3-4ce6-b9c7-1688fe1410f1 Microsoft.AspNetCore.Rewrite @@ -17,5 +17,5 @@ 2.0 - + diff --git a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ModRewriteExtensions.cs b/src/Microsoft.AspNetCore.Rewrite/ModRewriteExtensions.cs similarity index 60% rename from src/Microsoft.AspNetCore.Rewrite/ModRewrite/ModRewriteExtensions.cs rename to src/Microsoft.AspNetCore.Rewrite/ModRewriteExtensions.cs index a5c4986e53..c8af9432cc 100644 --- a/src/Microsoft.AspNetCore.Rewrite/ModRewrite/ModRewriteExtensions.cs +++ b/src/Microsoft.AspNetCore.Rewrite/ModRewriteExtensions.cs @@ -4,7 +4,7 @@ using System; using System.IO; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Rewrite.ModRewrite; +using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite; namespace Microsoft.AspNetCore.Rewrite { @@ -16,16 +16,16 @@ namespace Microsoft.AspNetCore.Rewrite /// The UrlRewrite options. /// /// The path to the file containing mod_rewrite rules. - public static UrlRewriteOptions ImportFromModRewrite(this UrlRewriteOptions options, IHostingEnvironment hostingEnv, string filePath) + public static RewriteOptions ImportFromModRewrite(this RewriteOptions options, IHostingEnvironment hostingEnv, string filePath) { if (options == null) { - throw new ArgumentNullException("UrlRewriteOptions is null"); + throw new ArgumentNullException(nameof(options)); } if (hostingEnv == null) { - throw new ArgumentNullException("HostingEnvironment is null"); + throw new ArgumentNullException(nameof(hostingEnv)); } if (string.IsNullOrEmpty(filePath)) @@ -46,36 +46,39 @@ namespace Microsoft.AspNetCore.Rewrite /// /// The UrlRewrite options. /// Text reader containing a stream of mod_rewrite rules. - public static UrlRewriteOptions ImportFromModRewrite(this UrlRewriteOptions options, TextReader reader) + public static RewriteOptions ImportFromModRewrite(this RewriteOptions options, TextReader reader) { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + if (reader == null) + { + throw new ArgumentNullException(nameof(reader)); + } options.Rules.AddRange(FileParser.Parse(reader)); return options; } /// /// Adds a mod_rewrite rule to the current rules. - /// Additional properties (conditions, flags) for the rule can be added through the action. /// /// The UrlRewrite options. /// The literal string of a mod_rewrite rule: /// "RewriteRule Pattern Substitution [Flags]" - /// Action to perform on the - public static UrlRewriteOptions AddModRewriteRule(this UrlRewriteOptions options, string rule, Action action) + public static RewriteOptions AddModRewriteRule(this RewriteOptions options, string rule) { - var builder = new RuleBuilder(rule); - action(builder); - options.Rules.Add(builder.Build()); - return options; - } + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + if (rule == null) + { + throw new ArgumentNullException(nameof(rule)); + } - /// - /// Adds a mod_rewrite rule to the current rules. - /// - /// The UrlRewrite options. - /// The literal string of a mod_rewrite rule: - /// "RewriteRule Pattern Substitution [Flags]" - public static UrlRewriteOptions AddModRewriteRule(this UrlRewriteOptions options, string rule) - { var builder = new RuleBuilder(rule); options.Rules.Add(builder.Build()); return options; diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewriteContext.cs b/src/Microsoft.AspNetCore.Rewrite/RewriteContext.cs similarity index 94% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewriteContext.cs rename to src/Microsoft.AspNetCore.Rewrite/RewriteContext.cs index ab97b358ef..12b1da7a48 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewriteContext.cs +++ b/src/Microsoft.AspNetCore.Rewrite/RewriteContext.cs @@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Rewrite /// /// The UrlRewrite Context contains the HttpContext of the request and the file provider to check conditions. /// - public class UrlRewriteContext + public class RewriteContext { public HttpContext HttpContext { get; set; } public IFileProvider FileProvider { get; set; } diff --git a/src/Microsoft.AspNetCore.Rewrite/RewriteExtensions.cs b/src/Microsoft.AspNetCore.Rewrite/RewriteExtensions.cs new file mode 100644 index 0000000000..50026ddc83 --- /dev/null +++ b/src/Microsoft.AspNetCore.Rewrite/RewriteExtensions.cs @@ -0,0 +1,35 @@ +// 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; + +namespace Microsoft.AspNetCore.Builder +{ + /// + /// Extension methods for the + /// + public static class RewriteExtensions + { + /// + /// Checks if a given Url matches rules and conditions, and modifies the HttpContext on match. + /// + /// + /// Options for urlrewrite. + /// + public static IApplicationBuilder UseRewriter(this IApplicationBuilder app, RewriteOptions options) + { + if (app == null) + { + throw new ArgumentNullException(nameof(app)); + } + + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + // put middleware in pipeline + return app.UseMiddleware(options); + } + } +} diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewriteMiddleware.cs b/src/Microsoft.AspNetCore.Rewrite/RewriteMiddleware.cs similarity index 85% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewriteMiddleware.cs rename to src/Microsoft.AspNetCore.Rewrite/RewriteMiddleware.cs index deb987d647..01c8b17d0a 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewriteMiddleware.cs +++ b/src/Microsoft.AspNetCore.Rewrite/RewriteMiddleware.cs @@ -5,7 +5,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Rewrite.RuleAbstraction; +using Microsoft.AspNetCore.Rewrite.Internal; using Microsoft.Extensions.FileProviders; namespace Microsoft.AspNetCore.Rewrite @@ -13,19 +13,19 @@ namespace Microsoft.AspNetCore.Rewrite /// /// Represents a middleware that rewrites urls imported from mod_rewrite, UrlRewrite, and code. /// - public class UrlRewriteMiddleware + public class RewriteMiddleware { private readonly RequestDelegate _next; - private readonly UrlRewriteOptions _options; + private readonly RewriteOptions _options; private readonly IFileProvider _fileProvider; /// - /// Creates a new instance of + /// Creates a new instance of /// /// The delegate representing the next middleware in the request pipeline. /// The Hosting Environment. /// The middleware options, containing the rules to apply. - public UrlRewriteMiddleware(RequestDelegate next, IHostingEnvironment hostingEnv, UrlRewriteOptions options) + public RewriteMiddleware(RequestDelegate next, IHostingEnvironment hostingEnv, RewriteOptions options) { if (next == null) { @@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.Rewrite { throw new ArgumentNullException(nameof(context)); } - var urlContext = new UrlRewriteContext { HttpContext = context, FileProvider = _fileProvider }; + var urlContext = new RewriteContext { HttpContext = context, FileProvider = _fileProvider }; foreach (var rule in _options.Rules) { // Apply the rule diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewriteOptions.cs b/src/Microsoft.AspNetCore.Rewrite/RewriteOptions.cs similarity index 79% rename from src/Microsoft.AspNetCore.Rewrite/UrlRewriteOptions.cs rename to src/Microsoft.AspNetCore.Rewrite/RewriteOptions.cs index becea3063e..71eb2fef99 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewriteOptions.cs +++ b/src/Microsoft.AspNetCore.Rewrite/RewriteOptions.cs @@ -2,15 +2,15 @@ // 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.RuleAbstraction; +using Microsoft.AspNetCore.Rewrite.Internal; using Microsoft.Extensions.FileProviders; namespace Microsoft.AspNetCore.Rewrite { /// - /// Options for the + /// Options for the /// - public class UrlRewriteOptions + public class RewriteOptions { /// /// The ordered list of rules to apply to the context. diff --git a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/RuleTermination.cs b/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/RuleTermination.cs deleted file mode 100644 index eae0a13ffa..0000000000 --- a/src/Microsoft.AspNetCore.Rewrite/RuleAbstraction/RuleTermination.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.Rewrite.RuleAbstraction -{ - public enum RuleTerminiation - { - Continue, - ResponseComplete, - StopRules - } -} diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/Conditions.cs b/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/Conditions.cs deleted file mode 100644 index 0e3ec81df7..0000000000 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/Conditions.cs +++ /dev/null @@ -1,14 +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.Collections.Generic; - -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite -{ - public class Conditions - { - public List ConditionList { get; set; } = new List(); - public LogicalGrouping MatchType { get; set; } // default is MatchAll - public bool TrackingAllCaptures { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/InitialMatch.cs b/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/InitialMatch.cs deleted file mode 100644 index bfbdcad006..0000000000 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/InitialMatch.cs +++ /dev/null @@ -1,14 +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.Text.RegularExpressions; - -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite -{ - public class InitialMatch - { - public Regex Url { get; set; } // TODO must be a non-empty string, throw in check after parsing? - public bool IgnoreCase { get; set; } = true; - public bool Negate { get; set; } - } -} diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlRewriteExtensions.cs b/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlRewriteExtensions.cs deleted file mode 100644 index b958d2ed60..0000000000 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlRewriteExtensions.cs +++ /dev/null @@ -1,44 +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.IO; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Rewrite.UrlRewrite; - -namespace Microsoft.AspNetCore.Rewrite -{ - public static class UrlRewriteExtensions - { - /// - /// Imports rules from a mod_rewrite file and adds the rules to current rules. - /// - /// The UrlRewrite options. - /// - /// The path to the file containing urlrewrite rules. - public static UrlRewriteOptions ImportFromUrlRewrite(this UrlRewriteOptions options, IHostingEnvironment hostingEnv, string filePath) - { - if (options == null) - { - throw new ArgumentNullException("UrlRewriteOptions is null"); - } - - if (hostingEnv == null) - { - throw new ArgumentNullException("HostingEnvironment is null"); - } - - if (string.IsNullOrEmpty(filePath)) - { - throw new ArgumentException(nameof(filePath)); - } - - var path = Path.Combine(hostingEnv.ContentRootPath, filePath); - using (var stream = File.OpenRead(path)) - { - options.Rules.AddRange(UrlRewriteFileParser.Parse(new StreamReader(stream))); - }; - return options; - } - } -} diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlRewriteFileParser.cs b/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlRewriteFileParser.cs deleted file mode 100644 index 454555c79e..0000000000 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlRewriteFileParser.cs +++ /dev/null @@ -1,228 +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 System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using System.Xml.Linq; - -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite -{ - // TODO rename - public static class UrlRewriteFileParser - { - private static readonly TimeSpan RegexTimeout = TimeSpan.FromMilliseconds(1); - public static List Parse(TextReader reader) - { - var temp = XDocument.Load(reader); - var xmlRoot = temp.Descendants(RewriteTags.Rewrite); - var rules = new List(); - - if (xmlRoot != null) - { - // there is a valid rewrite block, go through each rule and process - GetGlobalRules(xmlRoot.Descendants(RewriteTags.GlobalRules), rules); - GetRules(xmlRoot.Descendants(RewriteTags.Rules), rules); - } - return rules; - } - - private static void GetGlobalRules(IEnumerable globalRules, List result) - { - foreach (var rule in globalRules.Elements(RewriteTags.Rule) ?? Enumerable.Empty()) - { - var res = new UrlRewriteRule(); - SetRuleAttributes(rule, res); - // TODO handle full url with global rules - may or may not support - res.Action = CreateUrlAction(rule.Element(RewriteTags.Action)); - result.Add(res); - } - } - - private static void GetRules(IEnumerable rules, List result) - { - // TODO Better null check? - foreach (var rule in rules.Elements(RewriteTags.Rule) ?? Enumerable.Empty()) - { - var res = new UrlRewriteRule(); - SetRuleAttributes(rule, res); - res.Action = CreateUrlAction(rule.Element(RewriteTags.Action)); - result.Add(res); - } - } - - private static void SetRuleAttributes(XElement rule, UrlRewriteRule res) - { - if (rule == null) - { - return; - } - - res.Name = rule.Attribute(RewriteTags.Name)?.Value; - - bool enabled; - if (bool.TryParse(rule.Attribute(RewriteTags.Enabled)?.Value, out enabled)) - { - res.Enabled = enabled; - } - - PatternSyntax patternSyntax; - if (Enum.TryParse(rule.Attribute(RewriteTags.PatternSyntax)?.Value, out patternSyntax)) - { - res.PatternSyntax = patternSyntax; - } - - bool stopProcessing; - if (bool.TryParse(rule.Attribute(RewriteTags.StopProcessing)?.Value, out stopProcessing)) - { - res.StopProcessing = stopProcessing; - } - - res.Match = CreateMatch(rule.Element(RewriteTags.Match)); - res.Conditions = CreateConditions(rule.Element(RewriteTags.Conditions)); - } - - private static InitialMatch CreateMatch(XElement match) - { - if (match == null) - { - return null; - } - - var matchRes = new InitialMatch(); - - bool parBool; - if (bool.TryParse(match.Attribute(RewriteTags.IgnoreCase)?.Value, out parBool)) - { - matchRes.IgnoreCase = parBool; - } - - if (bool.TryParse(match.Attribute(RewriteTags.Negate)?.Value, out parBool)) - { - matchRes.Negate = parBool; - } - - var parsedInputString = match.Attribute(RewriteTags.Url)?.Value; - - if (matchRes.IgnoreCase) - { - matchRes.Url = new Regex(parsedInputString, RegexOptions.IgnoreCase | RegexOptions.Compiled, RegexTimeout); - } - else - { - matchRes.Url = new Regex(parsedInputString, RegexOptions.Compiled, RegexTimeout); - } - return matchRes; - } - - - private static Conditions CreateConditions(XElement conditions) - { - var condRes = new Conditions(); - if (conditions == null) - { - return condRes; // TODO make sure no null exception on Conditions - } - - LogicalGrouping grouping; - if (Enum.TryParse(conditions.Attribute(RewriteTags.MatchType)?.Value, out grouping)) - { - condRes.MatchType = grouping; - } - - bool parBool; - if (bool.TryParse(conditions.Attribute(RewriteTags.TrackingAllCaptures)?.Value, out parBool)) - { - condRes.TrackingAllCaptures = parBool; - } - - foreach (var cond in conditions.Elements(RewriteTags.Add)) - { - condRes.ConditionList.Add(CreateCondition(cond)); - } - return condRes; - } - - private static Condition CreateCondition(XElement condition) - { - if (condition == null) - { - return null; - } - - var condRes = new Condition(); - - bool parBool; - if (bool.TryParse(condition.Attribute(RewriteTags.IgnoreCase)?.Value, out parBool)) - { - condRes.IgnoreCase = parBool; - } - - if (bool.TryParse(condition.Attribute(RewriteTags.Negate)?.Value, out parBool)) - { - condRes.Negate = parBool; - } - - MatchType matchType; - if (Enum.TryParse(condition.Attribute(RewriteTags.MatchPattern)?.Value, out matchType)) - { - condRes.MatchType = matchType; - } - - var parsedInputString = condition.Attribute(RewriteTags.Input)?.Value; - if (parsedInputString != null) - { - condRes.Input = InputParser.ParseInputString(parsedInputString); - } - - parsedInputString = condition.Attribute(RewriteTags.Pattern)?.Value; - - if (condRes.IgnoreCase) - { - condRes.MatchPattern = new Regex(parsedInputString, RegexOptions.IgnoreCase | RegexOptions.Compiled, RegexTimeout); - } - else - { - condRes.MatchPattern = new Regex(parsedInputString, RegexOptions.Compiled, RegexTimeout); - } - return condRes; - } - - private static UrlAction CreateUrlAction(XElement urlAction) - { - if (urlAction == null) - { - throw new FormatException("Action is a required element of a rule."); - } - var actionRes = new UrlAction(); - - ActionType actionType; - if (Enum.TryParse(urlAction.Attribute(RewriteTags.Type)?.Value, out actionType)) - { - actionRes.Type = actionType; - } - - bool parseBool; - if (bool.TryParse(urlAction.Attribute(RewriteTags.AppendQuery)?.Value, out parseBool)) - { - actionRes.AppendQueryString = parseBool; - } - - if (bool.TryParse(urlAction.Attribute(RewriteTags.LogRewrittenUrl)?.Value, out parseBool)) - { - actionRes.LogRewrittenUrl = parseBool; - } - - RedirectType redirectType; - if (Enum.TryParse(urlAction.Attribute(RewriteTags.RedirectType)?.Value, out redirectType)) - { - actionRes.RedirectType = redirectType; - } - - actionRes.Url = InputParser.ParseInputString(urlAction.Attribute(RewriteTags.Url)?.Value); - return actionRes; - } - } -} diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlRewriteRule.cs b/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlRewriteRule.cs deleted file mode 100644 index db33219ed0..0000000000 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewrite/UrlRewriteRule.cs +++ /dev/null @@ -1,25 +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 Microsoft.AspNetCore.Rewrite.RuleAbstraction; - -namespace Microsoft.AspNetCore.Rewrite.UrlRewrite -{ - public class UrlRewriteRule : Rule - { - public string Name { get; set; } - public bool Enabled { get; set; } = true; - public PatternSyntax PatternSyntax { get; set; } - public bool StopProcessing { get; set; } - public InitialMatch Match { get; set; } - public Conditions Conditions { get; set; } - public UrlAction Action { get; set; } - - public override RuleResult ApplyRule(UrlRewriteContext context) - { - // TODO - throw new NotImplementedException(); - } - } -} diff --git a/src/Microsoft.AspNetCore.Rewrite/UrlRewriteExtensions.cs b/src/Microsoft.AspNetCore.Rewrite/UrlRewriteExtensions.cs index 2c0942f110..944426b055 100644 --- a/src/Microsoft.AspNetCore.Rewrite/UrlRewriteExtensions.cs +++ b/src/Microsoft.AspNetCore.Rewrite/UrlRewriteExtensions.cs @@ -2,34 +2,67 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.AspNetCore.Rewrite; +using System.IO; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite; -namespace Microsoft.AspNetCore.Builder +namespace Microsoft.AspNetCore.Rewrite { - /// - /// Extension methods for the - /// public static class UrlRewriteExtensions { /// - /// Checks if a given Url matches rules and conditions, and modifies the HttpContext on match. + /// Imports rules from a mod_rewrite file and adds the rules to current rules. /// - /// - /// Options for urlrewrite. - /// - public static IApplicationBuilder UseRewriter(this IApplicationBuilder app, UrlRewriteOptions options) + /// The UrlRewrite options. + /// + /// The path to the file containing urlrewrite rules. + public static RewriteOptions ImportFromUrlRewrite(this RewriteOptions options, IHostingEnvironment hostingEnv, string filePath) { - if (app == null) - { - throw new ArgumentNullException(nameof(app)); - } - if (options == null) { throw new ArgumentNullException(nameof(options)); } - // put middleware in pipeline - return app.UseMiddleware(options); + + if (hostingEnv == null) + { + throw new ArgumentNullException(nameof(hostingEnv)); + } + + if (string.IsNullOrEmpty(filePath)) + { + throw new ArgumentException(nameof(filePath)); + } + + var path = Path.Combine(hostingEnv.ContentRootPath, filePath); + using (var stream = File.OpenRead(path)) + { + options.Rules.AddRange(UrlRewriteFileParser.Parse(new StreamReader(stream))); + }; + return options; + } + + /// + /// Imports rules from a mod_rewrite file and adds the rules to current rules. + /// + /// The UrlRewrite options. + /// The text reader stream. + public static RewriteOptions ImportFromUrlRewrite(this RewriteOptions options, TextReader stream) + { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + if (stream == null) + { + throw new ArgumentException(nameof(stream)); + } + + using (stream) + { + options.Rules.AddRange(UrlRewriteFileParser.Parse(stream)); + }; + return options; } } } diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/ConditionActionTest.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ConditionActionTest.cs similarity index 97% rename from test/Microsoft.AspNetCore.Rewrite.Tests/ConditionActionTest.cs rename to test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ConditionActionTest.cs index 7f1a37f1b4..d49d9ef695 100644 --- a/test/Microsoft.AspNetCore.Rewrite.Tests/ConditionActionTest.cs +++ b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ConditionActionTest.cs @@ -1,10 +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.Rewrite.ModRewrite; +using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite; using Xunit; -namespace Microsoft.AspNetCore.Rewrite +namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite { public class ConditionActionTest { diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/FlagParserTest.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/FlagParserTest.cs similarity index 95% rename from test/Microsoft.AspNetCore.Rewrite.Tests/FlagParserTest.cs rename to test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/FlagParserTest.cs index dce8be83a0..572f376f2f 100644 --- a/test/Microsoft.AspNetCore.Rewrite.Tests/FlagParserTest.cs +++ b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/FlagParserTest.cs @@ -3,10 +3,10 @@ using System.Collections.Generic; using System.Linq; -using Microsoft.AspNetCore.Rewrite.ModRewrite; +using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite; using Xunit; -namespace Microsoft.AspNetCore.Rewrite +namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite { public class FlagParserTest { diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteConditionBuilderTest.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ModRewriteConditionBuilderTest.cs similarity index 92% rename from test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteConditionBuilderTest.cs rename to test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ModRewriteConditionBuilderTest.cs index 3436bcaef3..05f610046a 100644 --- a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteConditionBuilderTest.cs +++ b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ModRewriteConditionBuilderTest.cs @@ -1,11 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.AspNetCore.Rewrite.ModRewrite; -using Microsoft.AspNetCore.Rewrite.Operands; +using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite; +using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands; using Xunit; -namespace RewriteTest +namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite { // This file tests an input of a list of tokens and verifies that the appropriate condition is obtained public class ModRewriteConditionBuilderTest diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteFlagTest.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ModRewriteFlagTest.cs similarity index 84% rename from test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteFlagTest.cs rename to test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ModRewriteFlagTest.cs index e9938eff0c..ddc7329b37 100644 --- a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteFlagTest.cs +++ b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ModRewriteFlagTest.cs @@ -3,12 +3,12 @@ using System.Text.RegularExpressions; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Rewrite.ModRewrite; -using Microsoft.AspNetCore.Rewrite.Operands; -using Microsoft.AspNetCore.Rewrite.RuleAbstraction; +using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite; +using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite.Operands; +using Microsoft.AspNetCore.Rewrite.Internal; using Xunit; -namespace Microsoft.AspNetCore.Rewrite +namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite { public class ModRewriteFlagTest { @@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Rewrite [Fact] public void ModRewriteRule_Check403OnForbiddenFlag() { - var context = new UrlRewriteContext { HttpContext = CreateRequest("/", "/hey/hello") }; + var context = new RewriteContext { HttpContext = CreateRequest("/", "/hey/hello") }; var rule = new ModRewriteRule { InitialRule = new RuleExpression { Operand = new RegexOperand(new Regex("/hey/(.*)")) , Invert = false }, @@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Rewrite [Fact] public void ModRewriteRule_Check410OnGoneFlag() { - var context = new UrlRewriteContext { HttpContext = CreateRequest("/", "/hey/hello") }; + var context = new RewriteContext { HttpContext = CreateRequest("/", "/hey/hello") }; var rule = new ModRewriteRule { InitialRule = new RuleExpression { Operand = new RegexOperand(new Regex("/hey/(.*)")), Invert = false }, @@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Rewrite [Fact] public void ModRewriteRule_CheckLastFlag() { - var context = new UrlRewriteContext { HttpContext = CreateRequest("/", "/hey/hello") }; + var context = new RewriteContext { HttpContext = CreateRequest("/", "/hey/hello") }; var rule = new ModRewriteRule { InitialRule = new RuleExpression { Operand = new RegexOperand(new Regex("/hey/(.*)")), Invert = false }, @@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Rewrite public void ModRewriteRule_CheckRedirectFlag() { // TODO fix this test. - var context = new UrlRewriteContext { HttpContext = CreateRequest("/", "/hey/hello") }; + var context = new RewriteContext { HttpContext = CreateRequest("/", "/hey/hello") }; var rule = new ModRewriteRule { InitialRule = new RuleExpression { Operand = new RegexOperand(new Regex("/hey/(.*)")), Invert = false }, diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteMiddlewareTest.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ModRewriteMiddlewareTest.cs similarity index 82% rename from test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteMiddlewareTest.cs rename to test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ModRewriteMiddlewareTest.cs index 92c6dcb327..90a5d6dba1 100644 --- a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteMiddlewareTest.cs +++ b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/ModRewriteMiddlewareTest.cs @@ -10,14 +10,14 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.TestHost; using Xunit; -namespace Microsoft.AspNetCore.Rewrite +namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite { public class ModRewriteMiddlewareTest { [Fact] public async Task Invoke_RewritePathWhenMatching() { - var options = new UrlRewriteOptions().AddModRewriteRule("RewriteRule /hey/(.*) /$1 "); + var options = new RewriteOptions().AddModRewriteRule("RewriteRule /hey/(.*) /$1 "); var builder = new WebHostBuilder() .Configure(app => { @@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Rewrite [Fact] public async Task Invoke_RewritePathTerminatesOnFirstSuccessOfRule() { - var options = new UrlRewriteOptions().AddModRewriteRule("RewriteRule /hey/(.*) /$1 [L]") + var options = new RewriteOptions().AddModRewriteRule("RewriteRule /hey/(.*) /$1 [L]") .AddModRewriteRule("RewriteRule /hello /what"); var builder = new WebHostBuilder() .Configure(app => @@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.Rewrite [Fact] public async Task Invoke_RewritePathDoesNotTerminateOnFirstSuccessOfRule() { - var options = new UrlRewriteOptions().AddModRewriteRule("RewriteRule /hey/(.*) /$1") + var options = new RewriteOptions().AddModRewriteRule("RewriteRule /hey/(.*) /$1") .AddModRewriteRule("RewriteRule /hello /what"); var builder = new WebHostBuilder() .Configure(app => @@ -76,7 +76,7 @@ namespace Microsoft.AspNetCore.Rewrite [Fact] public async Task Invoke_ShouldIgnoreComments() { - var options = new UrlRewriteOptions().ImportFromModRewrite(new StringReader("#RewriteRule ^/hey/(.*) /$1 ")); + var options = new RewriteOptions().ImportFromModRewrite(new StringReader("#RewriteRule ^/hey/(.*) /$1 ")); var builder = new WebHostBuilder() .Configure(app => { @@ -95,7 +95,7 @@ namespace Microsoft.AspNetCore.Rewrite [Fact] public async Task Invoke_ShouldRewriteHomepage() { - var options = new UrlRewriteOptions().ImportFromModRewrite(new StringReader(@"RewriteRule ^/$ /homepage.html")); + var options = new RewriteOptions().ImportFromModRewrite(new StringReader(@"RewriteRule ^/$ /homepage.html")); var builder = new WebHostBuilder() .Configure(app => { @@ -112,7 +112,7 @@ namespace Microsoft.AspNetCore.Rewrite [Fact] public async Task Invoke_ShouldIgnorePorts() { - var options = new UrlRewriteOptions().ImportFromModRewrite(new StringReader(@"RewriteRule ^/$ /homepage.html")); + var options = new RewriteOptions().ImportFromModRewrite(new StringReader(@"RewriteRule ^/$ /homepage.html")); var builder = new WebHostBuilder() .Configure(app => { @@ -129,7 +129,7 @@ namespace Microsoft.AspNetCore.Rewrite [Fact] public async Task Invoke_HandleNegatedRewriteRules() { - var options = new UrlRewriteOptions().ImportFromModRewrite(new StringReader(@"RewriteRule !^/$ /homepage.html")); + var options = new RewriteOptions().ImportFromModRewrite(new StringReader(@"RewriteRule !^/$ /homepage.html")); var builder = new WebHostBuilder() .Configure(app => { @@ -146,7 +146,7 @@ namespace Microsoft.AspNetCore.Rewrite [Fact] public async Task Invoke_BackReferencesShouldBeApplied() { - var options = new UrlRewriteOptions().ImportFromModRewrite(new StringReader(@"RewriteRule (.*)\.aspx $1.php")); + var options = new RewriteOptions().ImportFromModRewrite(new StringReader(@"RewriteRule (.*)\.aspx $1.php")); var builder = new WebHostBuilder() .Configure(app => { @@ -169,7 +169,7 @@ namespace Microsoft.AspNetCore.Rewrite [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 UrlRewriteOptions().ImportFromModRewrite(new StringReader(rule)); + var options = new RewriteOptions().ImportFromModRewrite(new StringReader(rule)); var builder = new WebHostBuilder() .Configure(app => { @@ -183,28 +183,10 @@ namespace Microsoft.AspNetCore.Rewrite Assert.Equal(response, expected); } - [Fact(Skip="Need to handle escape characters")] - public async Task Invoke_HandleMultipleBackReferences() - { - var options = new UrlRewriteOptions() - .ImportFromModRewrite(new StringReader(@"RewriteRule ^/blog/([0-9]+)-([a-z]+) /blog/index.php?archive=$1-$2")); - var builder = new WebHostBuilder() - .Configure(app => - { - app.UseRewriter(options); - app.Run(context => context.Response.WriteAsync(context.Request.Path)); - }); - var server = new TestServer(builder); - - var response = await server.CreateClient().GetStringAsync("http://www.foo.org/blog/2016-jun"); - - Assert.Equal(response, @"/blog/index.php?archive=2016-jun"); - } - [Fact] public async Task Invoke_CheckFullUrlWithUFlagOnlyPath() { - var options = new UrlRewriteOptions() + var options = new RewriteOptions() .ImportFromModRewrite(new StringReader(@"RewriteRule (.+) http://www.example.com$1/ [U]")); var builder = new WebHostBuilder() .Configure(app => @@ -222,7 +204,7 @@ namespace Microsoft.AspNetCore.Rewrite [Fact] public async Task Invoke_CheckFullUrlWithUFlag() { - var options = new UrlRewriteOptions() + var options = new RewriteOptions() .ImportFromModRewrite(new StringReader(@"RewriteRule (.+) http://www.example.com$1/ [U]")); var builder = new WebHostBuilder() .Configure(app => @@ -240,7 +222,7 @@ namespace Microsoft.AspNetCore.Rewrite [Fact] public async Task Invoke_CheckModFileConditions() { - var options = new UrlRewriteOptions() + var options = new RewriteOptions() .ImportFromModRewrite(new StringReader(@"RewriteRule (.+) http://www.example.com$1/ [U]")); var builder = new WebHostBuilder() .Configure(app => @@ -259,7 +241,7 @@ namespace Microsoft.AspNetCore.Rewrite [InlineData("http://www.example.com/foo/")] public async Task Invoke_EnsureHttps(string input) { - var options = new UrlRewriteOptions() + var options = new RewriteOptions() .ImportFromModRewrite(new StringReader("RewriteCond %{REQUEST_URI} ^foo/ \nRewriteCond %{HTTPS} !on \nRewriteRule ^(.*)$ https://www.example.com$1 [R=301,L,U]")); var builder = new WebHostBuilder() .Configure(app => diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/RewriteTokenizerTest.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/RewriteTokenizerTest.cs similarity index 91% rename from test/Microsoft.AspNetCore.Rewrite.Tests/RewriteTokenizerTest.cs rename to test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/RewriteTokenizerTest.cs index 2961a3bb25..fdcaf6b35d 100644 --- a/test/Microsoft.AspNetCore.Rewrite.Tests/RewriteTokenizerTest.cs +++ b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/RewriteTokenizerTest.cs @@ -2,10 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using System.Linq; -using Microsoft.AspNetCore.Rewrite.ModRewrite; +using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite; using Xunit; -namespace Microsoft.AspNetCore.Rewrite + +namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite { public class RewriteTokenizerTest { diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/RuleAbstraction/RuleRegexParserTest.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/RuleRegexParserTest.cs similarity index 69% rename from test/Microsoft.AspNetCore.Rewrite.Tests/RuleAbstraction/RuleRegexParserTest.cs rename to test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/RuleRegexParserTest.cs index bb47b73069..5b3081a220 100644 --- a/test/Microsoft.AspNetCore.Rewrite.Tests/RuleAbstraction/RuleRegexParserTest.cs +++ b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewrite/RuleRegexParserTest.cs @@ -1,12 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Rewrite.ModRewrite; -using Microsoft.AspNetCore.Rewrite.Operands; -using Microsoft.AspNetCore.Rewrite.RuleAbstraction; +// 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.ModRewrite; using Xunit; -namespace Microsoft.AspNetCore.Rewrite.Tests.RuleAbstraction + +namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite { public class RuleRegexParserTest { diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteRuleBuilderTest.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteRuleBuilderTest.cs deleted file mode 100644 index a871f6daa2..0000000000 --- a/test/Microsoft.AspNetCore.Rewrite.Tests/ModRewriteRuleBuilderTest.cs +++ /dev/null @@ -1,14 +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 Microsoft.AspNetCore.Http; -using Xunit; - -namespace Microsoft.AspNetCore.Rewrite -{ - public class ModRewriteRuleBuilderTest - { - - } -} diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/Rewrite2MiddlewareTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/Rewrite2MiddlewareTests.cs deleted file mode 100644 index 7fb8806bdd..0000000000 --- a/test/Microsoft.AspNetCore.Rewrite.Tests/Rewrite2MiddlewareTests.cs +++ /dev/null @@ -1,92 +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.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Builder.Internal; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.TestHost; -using Xunit; - -namespace Microsoft.AspNetCore.Rewrite -{ - public class RewriteMiddlewareTests - { - - [Theory(Skip = "Adapting to TestServer")] - [InlineData("/foo", "", "/foo", "/yes")] - [InlineData("/foo", "", "/foo/", "/yes")] - [InlineData("/foo", "/Bar", "/foo", "/yes")] - [InlineData("/foo", "/Bar", "/foo/cho", "/yes")] - [InlineData("/foo", "/Bar", "/foo/cho/", "/yes")] - [InlineData("/foo/cho", "/Bar", "/foo/cho", "/yes")] - [InlineData("/foo/cho", "/Bar", "/foo/cho/do", "/yes")] - public void PathMatchFunc_RewriteDone(string matchPath, string basePath, string requestPath, string rewrite) - { - var context = CreateRequest(basePath, requestPath); - var options = new UrlRewriteOptions().RewritePath(matchPath, rewrite, false); - var builder = new ApplicationBuilder(serviceProvider: null) - .UseRewriter(options); - var app = builder.Build(); - app.Invoke(context).Wait(); - Assert.Equal(rewrite, context.Request.Path); - } - [Theory(Skip = "Adapting to TestServer")] - [InlineData(@"/(?\w+)?/(?\w+)?", @"", "/hey/hello", "/${id}/${name}", "/hello/hey")] - [InlineData(@"/(?\w+)?/(?\w+)?/(?\w+)?", @"", "/hey/hello/what", "/${temp}/${id}/${name}", "/what/hello/hey")] - public void PathMatchFunc_RegexRewriteDone(string matchPath, string basePath, string requestPath, string rewrite, string expected) - { - var context = CreateRequest(basePath, requestPath); - var options = new UrlRewriteOptions().RewritePath(matchPath, rewrite, false); - var builder = new ApplicationBuilder(serviceProvider: null) - .UseRewriter(options); - - var app = builder.Build(); - app.Invoke(context).Wait(); - Assert.Equal(expected, context.Request.Path); - } - - [Fact(Skip = "Adapting to TestServer")] - public void PathMatchFunc_RedirectScheme() - { - HttpContext context = CreateRequest("/", "/"); - context.Request.Scheme = "http"; - var options = new UrlRewriteOptions().RedirectScheme(30); - var builder = new ApplicationBuilder(serviceProvider: null) - .UseRewriter(options); - var app = builder.Build(); - app.Invoke(context).Wait(); - Assert.True(context.Response.Headers["location"].First().StartsWith("https")); - } - - [Theory(Skip = "Adapting to TestServer")] - public async Task PathMatchFunc_RewriteScheme() - { - var options = new UrlRewriteOptions().RewriteScheme(); - var builder = new WebHostBuilder() - .Configure(app => - { - app.UseRewriter(options); - - app.Run(context => context.Response.WriteAsync(context.Request.Path)); - }); - var server = new TestServer(builder); - - var response = await server.CreateClient().GetAsync("http://foo.com/bar"); - - //Assert.True(response.RequestMessage.); - } - - - private HttpContext CreateRequest(string basePath, string requestPath) - { - HttpContext context = new DefaultHttpContext(); - context.Request.PathBase = new PathString(basePath); - context.Request.Path = new PathString(requestPath); - context.Request.Host = new HostString("example.com"); - return context; - } - } -} diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FileParserTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FileParserTests.cs index d2f42c21a3..4cdfe347aa 100644 --- a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FileParserTests.cs +++ b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/FileParserTests.cs @@ -4,7 +4,10 @@ using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; -using Microsoft.AspNetCore.Rewrite.UrlRewrite; +using Microsoft.AspNetCore.Rewrite.Internal; +using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite; +using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlActions; +using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite.UrlMatches; using Xunit; namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite @@ -35,7 +38,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite var res = UrlRewriteFileParser.Parse(new StringReader(xml)); // assert - AssertUrlRewriteRuleEquality(res, expected); + AssertUrlRewriteRuleEquality(res, expected); } [Fact] @@ -58,7 +61,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite condList.Add(new Condition { Input = InputParser.ParseInputString("{HTTPS}"), - MatchPattern = new Regex("^OFF$") + Match = new RegexMatch(new Regex("^OFF$"), false) }); var expected = new List(); @@ -70,9 +73,9 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite // act var res = UrlRewriteFileParser.Parse(new StringReader(xml)); - + // assert - AssertUrlRewriteRuleEquality(expected, res); + AssertUrlRewriteRuleEquality(res, expected); } [Fact] @@ -88,12 +91,12 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite - + - + "; @@ -102,7 +105,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite condList.Add(new Condition { Input = InputParser.ParseInputString("{HTTPS}"), - MatchPattern = new Regex("^OFF$") + Match = new RegexMatch(new Regex("^OFF$"), false) }); var expected = new List(); @@ -113,15 +116,15 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite pattern: "article.aspx?id={R:1}&title={R:2}")); expected.Add(CreateTestRule(condList, Url: "^article/([0-9]+)/([_0-9a-z-]+)", - name: "Rewrite to article.aspx", - actionType: ActionType.Redirect, + name: "Rewrite to another article.aspx", + actionType: ActionType.Rewrite, pattern: "article.aspx?id={R:1}&title={R:2}")); // act var res = UrlRewriteFileParser.Parse(new StringReader(xml)); // assert - AssertUrlRewriteRuleEquality(expected, res); + AssertUrlRewriteRuleEquality(res, expected); } // Creates a rule with appropriate default values of the url rewrite rule. @@ -144,23 +147,13 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite { return new UrlRewriteRule { - Action = new UrlAction - { - Url = InputParser.ParseInputString(pattern), - Type = actionType, - AppendQueryString = appendQueryString, - LogRewrittenUrl = rewrittenUrl, - RedirectType = redirectType - }, + Action = new RewriteAction(RuleTerminiation.Continue, InputParser.ParseInputString(Url), clearQuery: false), Name = name, Enabled = enabled, StopProcessing = stopProcessing, PatternSyntax = patternSyntax, - Match = new InitialMatch + InitialMatch = new RegexMatch(new Regex("^OFF$"), false) { - Url = new Regex(Url), - IgnoreCase = ignoreCase, - Negate = negate }, Conditions = new Conditions { @@ -184,14 +177,6 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite Assert.Equal(r1.StopProcessing, r2.StopProcessing); Assert.Equal(r1.PatternSyntax, r2.PatternSyntax); - Assert.Equal(r1.Match.IgnoreCase, r2.Match.IgnoreCase); - Assert.Equal(r1.Match.Negate, r2.Match.Negate); - - Assert.Equal(r1.Action.Type, r2.Action.Type); - Assert.Equal(r1.Action.AppendQueryString, r2.Action.AppendQueryString); - Assert.Equal(r1.Action.RedirectType, r2.Action.RedirectType); - Assert.Equal(r1.Action.LogRewrittenUrl, r2.Action.LogRewrittenUrl); - // TODO conditions, url pattern, initial match regex Assert.Equal(r1.Conditions.MatchType, r2.Conditions.MatchType); Assert.Equal(r1.Conditions.TrackingAllCaptures, r2.Conditions.TrackingAllCaptures); @@ -201,12 +186,9 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite { var c1 = r1.Conditions.ConditionList[j]; var c2 = r2.Conditions.ConditionList[j]; - Assert.Equal(c1.IgnoreCase, c2.IgnoreCase); - Assert.Equal(c1.Negate, c2.Negate); - Assert.Equal(c1.MatchType, c2.MatchType); Assert.Equal(c1.Input.PatternSegments.Count, c2.Input.PatternSegments.Count); } } } } -} +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/InputParserTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/InputParserTests.cs index 037804f267..bfcc08fc6d 100644 --- a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/InputParserTests.cs +++ b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/InputParserTests.cs @@ -2,12 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; -using System.Linq; using System.Text.RegularExpressions; -using System.Threading.Tasks; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Rewrite.UrlRewrite; +using Microsoft.AspNetCore.Rewrite.Internal.UrlRewrite; using Xunit; namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite @@ -21,8 +18,8 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite var result = InputParser.ParseInputString(testString); Assert.Equal(result.PatternSegments.Count, 1); } - - // Tests sizes of the pattern segments. These are all anonyomus lambdas, so cant check contents. + + // TODO update tests to check type [Theory] [InlineData("foo/bar/{R:1}/what", 3)] [InlineData("foo/{R:1}", 2)] @@ -35,7 +32,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite Assert.Equal(result.PatternSegments.Count, expected); } - // Test actual evaluation of the lambdas, verifying the correct string comes from the evalation + // Test actual evaluation of the types, verifying the correct string comes from the evalation [Theory] [InlineData("hey/hello/what", "hey/hello/what")] [InlineData("hey/{R:1}/what", "hey/foo/what")] @@ -98,16 +95,16 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite return context; } - private Match CreateTestRuleMatch() + private MatchResults CreateTestRuleMatch() { var match = Regex.Match("foo/bar/baz", "(.*)/(.*)/(.*)"); - return match; + return new MatchResults { BackReference = match.Groups, Success = match.Success }; } - private Match CreateTestCondMatch() + private MatchResults CreateTestCondMatch() { var match = Regex.Match("foo/bar/baz", "(.*)/(.*)/(.*)"); - return match; + return new MatchResults { BackReference = match.Groups, Success = match.Success }; } } } diff --git a/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/MiddleWareTests.cs b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/MiddleWareTests.cs new file mode 100644 index 0000000000..a34101b375 --- /dev/null +++ b/test/Microsoft.AspNetCore.Rewrite.Tests/UrlRewrite/MiddleWareTests.cs @@ -0,0 +1,259 @@ +// 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.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Net.Http.Headers; +using Xunit; + +namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite +{ + public class MiddlewareTests + { + [Fact] + public async Task Invoke_RedirectPathToPathAndQuery() + { + var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@" + + + + + + + ")); + var builder = new WebHostBuilder() + .Configure(app => + { + app.UseRewriter(options); + app.Run(context => context.Response.WriteAsync(context.Response.Headers[HeaderNames.Location])); + }); + var server = new TestServer(builder); + + var response = await server.CreateClient().GetAsync("article/10/hey"); + + Assert.Equal(response.Headers.Location.OriginalString, "article.aspx?id=10&title=hey"); + } + + [Fact] + public async Task Invoke_RewritePathToPathAndQuery() + { + var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@" + + + + + + + ")); + var builder = new WebHostBuilder() + .Configure(app => + { + app.UseRewriter(options); + app.Run(context => context.Response.WriteAsync(context.Request.Path + context.Request.QueryString)); + }); + var server = new TestServer(builder); + + var response = await server.CreateClient().GetStringAsync("/article/10/hey"); + + Assert.Equal(response, "/article.aspx?id=10&title=hey"); + } + + [Fact] + public async Task Invoke_RewriteBasedOnQueryStringParameters() + { + var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@" + + + + + + + + + + + ")); + var builder = new WebHostBuilder() + .Configure(app => + { + app.UseRewriter(options); + app.Run(context => context.Response.WriteAsync(context.Request.Path + context.Request.QueryString)); + }); + var server = new TestServer(builder); + + var response = await server.CreateClient().GetStringAsync("page.asp?p2=321&p1=123"); + + Assert.Equal(response, "/newpage.aspx?param1=123¶m2=321"); + } + + [Fact] + public async Task Invoke_RedirectToLowerCase() + { + var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@" + + + + + + + ")); + var builder = new WebHostBuilder() + .Configure(app => + { + app.UseRewriter(options); + app.Run(context => context.Response.WriteAsync(context.Response.Headers[HeaderNames.Location])); + }); + var server = new TestServer(builder); + + var response = await server.CreateClient().GetAsync("HElLo"); + + Assert.Equal(response.Headers.Location.OriginalString, "hello"); + } + + [Fact] + public async Task Invoke_RedirectRemoveTrailingSlash() + { + var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@" + + + + + + + + + + + ")); + var builder = new WebHostBuilder() + .Configure(app => + { + app.UseRewriter(options); + }); + var server = new TestServer(builder); + + var response = await server.CreateClient().GetAsync("hey/hello/"); + + Assert.Equal(response.Headers.Location.OriginalString, "hey/hello"); + } + + [Fact] + public async Task Invoke_RedirectAddTrailingSlash() + { + var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@" + + + + + + + + + + + ")); + var builder = new WebHostBuilder() + .Configure(app => + { + app.UseRewriter(options); + }); + var server = new TestServer(builder); + + var response = await server.CreateClient().GetAsync("hey/hello"); + + Assert.Equal(response.Headers.Location.OriginalString, "hey/hello/"); + } + + [Fact] + public async Task Invoke_RedirectToHttps() + { + var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@" + + + + + + + + + + ")); + var builder = new WebHostBuilder() + .Configure(app => + { + app.UseRewriter(options); + }); + var server = new TestServer(builder); + + var response = await server.CreateClient().GetAsync(new Uri("http://example.com")); + + Assert.Equal(response.Headers.Location.OriginalString, "https://example.com/"); + } + + [Fact] + public async Task Invoke_RewriteToHttps() + { + var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@" + + + + + + + + + + ")); + var builder = new WebHostBuilder() + .Configure(app => + { + app.UseRewriter(options); + app.Run(context => context.Response.WriteAsync( + context.Request.Scheme + + "://" + + context.Request.Host + + context.Request.Path + + context.Request.QueryString)); + }); + var server = new TestServer(builder); + + var response = await server.CreateClient().GetStringAsync(new Uri("http://example.com")); + + Assert.Equal(response, "https://example.com/"); + } + + [Fact] + public async Task Invoke_ReverseProxyToAnotherSite() + { + var options = new RewriteOptions().ImportFromUrlRewrite(new StringReader(@" + + + + + + + ")); + var builder = new WebHostBuilder() + .Configure(app => + { + app.UseRewriter(options); + app.Run(context => context.Response.WriteAsync( + context.Request.Scheme + + "://" + + context.Request.Host + + context.Request.Path + + context.Request.QueryString)); + }); + var server = new TestServer(builder); + + var response = await server.CreateClient().GetStringAsync(new Uri("http://example.com/")); + + Assert.Equal(response, "http://internalserver/"); + } + } +}