diff --git a/src/Middleware/Middleware.sln b/src/Middleware/Middleware.sln
index 44be9e8d3bec..bccbab07c9e2 100644
--- a/src/Middleware/Middleware.sln
+++ b/src/Middleware/Middleware.sln
@@ -281,6 +281,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{179A
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HeaderPropagationSample", "HeaderPropagation\samples\HeaderPropagationSample\HeaderPropagationSample.csproj", "{CDE2E736-A034-4748-98C4-0DEDAAC8063D}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.IIS", "..\Servers\IIS\IIS\src\Microsoft.AspNetCore.Server.IIS.csproj", "{B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1527,6 +1529,18 @@ Global
{CDE2E736-A034-4748-98C4-0DEDAAC8063D}.Release|x64.Build.0 = Release|Any CPU
{CDE2E736-A034-4748-98C4-0DEDAAC8063D}.Release|x86.ActiveCfg = Release|Any CPU
{CDE2E736-A034-4748-98C4-0DEDAAC8063D}.Release|x86.Build.0 = Release|Any CPU
+ {B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Debug|x64.Build.0 = Debug|Any CPU
+ {B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Debug|x86.Build.0 = Debug|Any CPU
+ {B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Release|x64.ActiveCfg = Release|Any CPU
+ {B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Release|x64.Build.0 = Release|Any CPU
+ {B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Release|x86.ActiveCfg = Release|Any CPU
+ {B9BE1823-B555-4AAB-AEBC-C8C3F48C8861}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1648,6 +1662,7 @@ Global
{8CDBD9C6-96D8-4987-AFCD-D248FBC7F02D} = {0437D207-864E-429C-92B4-9D08D290188C}
{179A159B-87EA-4353-BE92-4FB6CC05BC7D} = {0437D207-864E-429C-92B4-9D08D290188C}
{CDE2E736-A034-4748-98C4-0DEDAAC8063D} = {179A159B-87EA-4353-BE92-4FB6CC05BC7D}
+ {B9BE1823-B555-4AAB-AEBC-C8C3F48C8861} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {83786312-A93B-4BB4-AB06-7C6913A59AFA}
diff --git a/src/Middleware/Rewrite/ref/Microsoft.AspNetCore.Rewrite.csproj b/src/Middleware/Rewrite/ref/Microsoft.AspNetCore.Rewrite.csproj
index a4014b3f9491..587668329e38 100644
--- a/src/Middleware/Rewrite/ref/Microsoft.AspNetCore.Rewrite.csproj
+++ b/src/Middleware/Rewrite/ref/Microsoft.AspNetCore.Rewrite.csproj
@@ -7,6 +7,7 @@
+
diff --git a/src/Middleware/Rewrite/ref/Microsoft.AspNetCore.Rewrite.netcoreapp3.0.cs b/src/Middleware/Rewrite/ref/Microsoft.AspNetCore.Rewrite.netcoreapp3.0.cs
index 180d85f51d16..d807634f4979 100644
--- a/src/Middleware/Rewrite/ref/Microsoft.AspNetCore.Rewrite.netcoreapp3.0.cs
+++ b/src/Middleware/Rewrite/ref/Microsoft.AspNetCore.Rewrite.netcoreapp3.0.cs
@@ -18,8 +18,8 @@ public static partial class ApacheModRewriteOptionsExtensions
}
public static partial class IISUrlRewriteOptionsExtensions
{
- public static Microsoft.AspNetCore.Rewrite.RewriteOptions AddIISUrlRewrite(this Microsoft.AspNetCore.Rewrite.RewriteOptions options, Microsoft.Extensions.FileProviders.IFileProvider fileProvider, string filePath) { throw null; }
- public static Microsoft.AspNetCore.Rewrite.RewriteOptions AddIISUrlRewrite(this Microsoft.AspNetCore.Rewrite.RewriteOptions options, System.IO.TextReader reader) { throw null; }
+ public static Microsoft.AspNetCore.Rewrite.RewriteOptions AddIISUrlRewrite(this Microsoft.AspNetCore.Rewrite.RewriteOptions options, Microsoft.Extensions.FileProviders.IFileProvider fileProvider, string filePath, bool alwaysUseManagedServerVariables = false) { throw null; }
+ public static Microsoft.AspNetCore.Rewrite.RewriteOptions AddIISUrlRewrite(this Microsoft.AspNetCore.Rewrite.RewriteOptions options, System.IO.TextReader reader, bool alwaysUseManagedServerVariables = false) { throw null; }
}
public partial interface IRule
{
@@ -366,7 +366,7 @@ public virtual void ApplyRule(Microsoft.AspNetCore.Rewrite.RewriteContext contex
public partial class InputParser
{
public InputParser() { }
- public InputParser(Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite.IISRewriteMapCollection rewriteMaps) { }
+ public InputParser(Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite.IISRewriteMapCollection rewriteMaps, bool alwaysUseManagedServerVariables) { }
public Microsoft.AspNetCore.Rewrite.Internal.Pattern ParseInputString(string testString) { throw null; }
public Microsoft.AspNetCore.Rewrite.Internal.Pattern ParseInputString(string testString, Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite.UriMatchPart uriMatchPart) { throw null; }
}
@@ -443,7 +443,7 @@ public static partial class RewriteTags
}
public static partial class ServerVariables
{
- public static Microsoft.AspNetCore.Rewrite.Internal.PatternSegment FindServerVariable(string serverVariable, Microsoft.AspNetCore.Rewrite.Internal.ParserContext context, Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite.UriMatchPart uriMatchPart) { throw null; }
+ public static Microsoft.AspNetCore.Rewrite.Internal.PatternSegment FindServerVariable(string serverVariable, Microsoft.AspNetCore.Rewrite.Internal.ParserContext context, Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite.UriMatchPart uriMatchPart, bool alwaysUseManagedServerVariables) { throw null; }
}
public partial class UriMatchCondition : Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite.Condition
{
@@ -457,7 +457,7 @@ public enum UriMatchPart
public partial class UrlRewriteFileParser
{
public UrlRewriteFileParser() { }
- public System.Collections.Generic.IList Parse(System.IO.TextReader reader) { throw null; }
+ public System.Collections.Generic.IList Parse(System.IO.TextReader reader, bool alwaysUseManagedServerVariables) { throw null; }
}
public partial class UrlRewriteRuleBuilder
{
diff --git a/src/Middleware/Rewrite/src/IISUrlRewriteOptionsExtensions.cs b/src/Middleware/Rewrite/src/IISUrlRewriteOptionsExtensions.cs
index e31819b1116b..600a3c065621 100644
--- a/src/Middleware/Rewrite/src/IISUrlRewriteOptionsExtensions.cs
+++ b/src/Middleware/Rewrite/src/IISUrlRewriteOptionsExtensions.cs
@@ -1,8 +1,9 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// 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.Http.Features;
using Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;
using Microsoft.Extensions.FileProviders;
@@ -19,7 +20,8 @@ public static class IISUrlRewriteOptionsExtensions
/// The
/// The
/// The path to the file containing UrlRewrite rules.
- public static RewriteOptions AddIISUrlRewrite(this RewriteOptions options, IFileProvider fileProvider, string filePath)
+ /// Server variables are by default sourced from the server if it supports the feature. Use true to disable that behavior
+ public static RewriteOptions AddIISUrlRewrite(this RewriteOptions options, IFileProvider fileProvider, string filePath, bool alwaysUseManagedServerVariables = false)
{
if (options == null)
{
@@ -35,7 +37,7 @@ public static RewriteOptions AddIISUrlRewrite(this RewriteOptions options, IFile
using (var stream = file.CreateReadStream())
{
- return AddIISUrlRewrite(options, new StreamReader(stream));
+ return AddIISUrlRewrite(options, new StreamReader(stream), alwaysUseManagedServerVariables);
}
}
@@ -44,7 +46,8 @@ public static RewriteOptions AddIISUrlRewrite(this RewriteOptions options, IFile
///
/// The
/// The text reader stream.
- public static RewriteOptions AddIISUrlRewrite(this RewriteOptions options, TextReader reader)
+ /// Server variables are by default sourced from the server if it supports the feature. Use true to disable that behavior
+ public static RewriteOptions AddIISUrlRewrite(this RewriteOptions options, TextReader reader, bool alwaysUseManagedServerVariables = false)
{
if (options == null)
{
@@ -56,7 +59,7 @@ public static RewriteOptions AddIISUrlRewrite(this RewriteOptions options, TextR
throw new ArgumentException(nameof(reader));
}
- var rules = new UrlRewriteFileParser().Parse(reader);
+ var rules = new UrlRewriteFileParser().Parse(reader, alwaysUseManagedServerVariables);
foreach (var rule in rules)
{
@@ -66,4 +69,4 @@ public static RewriteOptions AddIISUrlRewrite(this RewriteOptions options, TextR
return options;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Middleware/Rewrite/src/Internal/IISUrlRewrite/InputParser.cs b/src/Middleware/Rewrite/src/Internal/IISUrlRewrite/InputParser.cs
index 53c63dfb6dd5..a68ef08bd503 100644
--- a/src/Middleware/Rewrite/src/Internal/IISUrlRewrite/InputParser.cs
+++ b/src/Middleware/Rewrite/src/Internal/IISUrlRewrite/InputParser.cs
@@ -1,4 +1,4 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// 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;
@@ -14,14 +14,16 @@ public class InputParser
private const char OpenBrace = '{';
private const char CloseBrace = '}';
private readonly IISRewriteMapCollection _rewriteMaps;
+ private readonly bool _alwaysUseManagedServerVariables;
public InputParser()
{
}
- public InputParser(IISRewriteMapCollection rewriteMaps)
+ public InputParser(IISRewriteMapCollection rewriteMaps, bool alwaysUseManagedServerVariables)
{
_rewriteMaps = rewriteMaps;
+ _alwaysUseManagedServerVariables = alwaysUseManagedServerVariables;
}
///
@@ -98,7 +100,7 @@ private void ParseParameter(ParserContext context, IList results
{
// This is just a server variable, so we do a lookup and verify the server variable exists.
parameter = context.Capture();
- results.Add(ServerVariables.FindServerVariable(parameter, context, uriMatchPart));
+ results.Add(ServerVariables.FindServerVariable(parameter, context, uriMatchPart, _alwaysUseManagedServerVariables));
return;
}
else if (context.Current == Colon)
diff --git a/src/Middleware/Rewrite/src/Internal/IISUrlRewrite/ServerVariables.cs b/src/Middleware/Rewrite/src/Internal/IISUrlRewrite/ServerVariables.cs
index 35e6ce12375f..cc991ca6642a 100644
--- a/src/Middleware/Rewrite/src/Internal/IISUrlRewrite/ServerVariables.cs
+++ b/src/Middleware/Rewrite/src/Internal/IISUrlRewrite/ServerVariables.cs
@@ -1,4 +1,4 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// 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;
@@ -15,58 +15,89 @@ public static class ServerVariables
/// The server variable
/// The parser context which is utilized when an exception is thrown
/// Indicates whether the full URI or the path should be evaluated for URL segments
+ /// Determines whether server variables are sourced from the managed server
/// Thrown when the server variable is unknown
/// The matching
- public static PatternSegment FindServerVariable(string serverVariable, ParserContext context, UriMatchPart uriMatchPart)
+ public static PatternSegment FindServerVariable(string serverVariable, ParserContext context, UriMatchPart uriMatchPart, bool alwaysUseManagedServerVariables)
{
+ Func managedVariableThunk = default;
+
switch (serverVariable)
{
// TODO Add all server variables here.
case "ALL_RAW":
- throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));
+ managedVariableThunk = () => throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));
+ break;
case "APP_POOL_ID":
- throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));
+ managedVariableThunk = () => throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));
+ break;
case "CONTENT_LENGTH":
- return new HeaderSegment(HeaderNames.ContentLength);
+ managedVariableThunk = () => new HeaderSegment(HeaderNames.ContentLength);
+ break;
case "CONTENT_TYPE":
- return new HeaderSegment(HeaderNames.ContentType);
+ managedVariableThunk = () => new HeaderSegment(HeaderNames.ContentType);
+ break;
case "HTTP_ACCEPT":
- return new HeaderSegment(HeaderNames.Accept);
+ managedVariableThunk = () => new HeaderSegment(HeaderNames.Accept);
+ break;
case "HTTP_COOKIE":
- return new HeaderSegment(HeaderNames.Cookie);
+ managedVariableThunk = () => new HeaderSegment(HeaderNames.Cookie);
+ break;
case "HTTP_HOST":
- return new HeaderSegment(HeaderNames.Host);
+ managedVariableThunk = () => new HeaderSegment(HeaderNames.Host);
+ break;
case "HTTP_REFERER":
- return new HeaderSegment(HeaderNames.Referer);
+ managedVariableThunk = () => new HeaderSegment(HeaderNames.Referer);
+ break;
case "HTTP_USER_AGENT":
- return new HeaderSegment(HeaderNames.UserAgent);
+ managedVariableThunk = () => new HeaderSegment(HeaderNames.UserAgent);
+ break;
case "HTTP_CONNECTION":
- return new HeaderSegment(HeaderNames.Connection);
+ managedVariableThunk = () => new HeaderSegment(HeaderNames.Connection);
+ break;
case "HTTP_URL":
- return new UrlSegment(uriMatchPart);
+ managedVariableThunk = () => new UrlSegment(uriMatchPart);
+ break;
case "HTTPS":
- return new IsHttpsUrlSegment();
+ managedVariableThunk = () => new IsHttpsUrlSegment();
+ break;
case "LOCAL_ADDR":
- return new LocalAddressSegment();
+ managedVariableThunk = () => new LocalAddressSegment();
+ break;
case "HTTP_PROXY_CONNECTION":
- throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));
+ managedVariableThunk = () => throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));
+ break;
case "QUERY_STRING":
- return new QueryStringSegment();
+ managedVariableThunk = () => new QueryStringSegment();
+ break;
case "REMOTE_ADDR":
- return new RemoteAddressSegment();
+ managedVariableThunk = () => new RemoteAddressSegment();
+ break;
case "REMOTE_HOST":
- throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));
+ managedVariableThunk = () => throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));
+ break;
case "REMOTE_PORT":
- return new RemotePortSegment();
+ managedVariableThunk = () => new RemotePortSegment();
+ break;
case "REQUEST_FILENAME":
- return new RequestFileNameSegment();
+ managedVariableThunk = () => new RequestFileNameSegment();
+ break;
case "REQUEST_METHOD":
- return new RequestMethodSegment();
+ managedVariableThunk = () => new RequestMethodSegment();
+ break;
case "REQUEST_URI":
- return new UrlSegment(uriMatchPart);
+ managedVariableThunk = () => new UrlSegment(uriMatchPart);
+ break;
default:
throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(serverVariable, context.Index));
}
+
+ if (alwaysUseManagedServerVariables)
+ {
+ return managedVariableThunk();
+ }
+
+ return new IISServerVariableSegment(serverVariable, managedVariableThunk);
}
}
}
diff --git a/src/Middleware/Rewrite/src/Internal/IISUrlRewrite/UrlRewriteFileParser.cs b/src/Middleware/Rewrite/src/Internal/IISUrlRewrite/UrlRewriteFileParser.cs
index 6bb08f41f1d2..97cc7ce4715b 100644
--- a/src/Middleware/Rewrite/src/Internal/IISUrlRewrite/UrlRewriteFileParser.cs
+++ b/src/Middleware/Rewrite/src/Internal/IISUrlRewrite/UrlRewriteFileParser.cs
@@ -1,4 +1,4 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// 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;
@@ -20,7 +20,8 @@ public class UrlRewriteFileParser
/// Parse an IIS rewrite section into a list of s.
///
/// The reader containing the rewrite XML
- public IList Parse(TextReader reader)
+ /// Determines whether server variables will be sourced from the managed server
+ public IList Parse(TextReader reader, bool alwaysUseManagedServerVariables)
{
var xmlDoc = XDocument.Load(reader, LoadOptions.SetLineInfo);
var xmlRoot = xmlDoc.Descendants(RewriteTags.Rewrite).FirstOrDefault();
@@ -30,7 +31,7 @@ public IList Parse(TextReader reader)
return null;
}
- _inputParser = new InputParser(RewriteMapParser.Parse(xmlRoot));
+ _inputParser = new InputParser(RewriteMapParser.Parse(xmlRoot), alwaysUseManagedServerVariables);
var result = new List();
ParseRules(xmlRoot.Descendants(RewriteTags.GlobalRules).FirstOrDefault(), result, global: true);
diff --git a/src/Middleware/Rewrite/src/Internal/PatternSegments/IISServerVariableSegment.cs b/src/Middleware/Rewrite/src/Internal/PatternSegments/IISServerVariableSegment.cs
new file mode 100644
index 000000000000..30504d54a4f1
--- /dev/null
+++ b/src/Middleware/Rewrite/src/Internal/PatternSegments/IISServerVariableSegment.cs
@@ -0,0 +1,25 @@
+// 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.Server.IIS;
+
+namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments
+{
+ internal class IISServerVariableSegment : PatternSegment
+ {
+ private readonly string _variableName;
+ private readonly Func _fallbackThunk;
+
+ public IISServerVariableSegment(string variableName, Func fallbackThunk)
+ {
+ _variableName = variableName;
+ _fallbackThunk = fallbackThunk;
+ }
+
+ public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)
+ {
+ return context.HttpContext.GetIISServerVariable(_variableName) ?? _fallbackThunk().Evaluate(context, ruleBackReferences, conditionBackReferences);
+ }
+ }
+}
diff --git a/src/Middleware/Rewrite/src/Microsoft.AspNetCore.Rewrite.csproj b/src/Middleware/Rewrite/src/Microsoft.AspNetCore.Rewrite.csproj
index d203b74371d3..be6f19ceb739 100644
--- a/src/Middleware/Rewrite/src/Microsoft.AspNetCore.Rewrite.csproj
+++ b/src/Middleware/Rewrite/src/Microsoft.AspNetCore.Rewrite.csproj
@@ -15,6 +15,7 @@
+
diff --git a/src/Middleware/Rewrite/test/IISUrlRewrite/FileParserTests.cs b/src/Middleware/Rewrite/test/IISUrlRewrite/FileParserTests.cs
index 18f1a246d0f8..e4ae35323f1d 100644
--- a/src/Middleware/Rewrite/test/IISUrlRewrite/FileParserTests.cs
+++ b/src/Middleware/Rewrite/test/IISUrlRewrite/FileParserTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// 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;
@@ -35,7 +35,7 @@ public void RuleParse_ParseTypicalRule()
pattern: "article.aspx?id={R:1}&title={R:2}"));
// act
- var res = new UrlRewriteFileParser().Parse(new StringReader(xml));
+ var res = new UrlRewriteFileParser().Parse(new StringReader(xml), false);
// assert
AssertUrlRewriteRuleEquality(expected, res);
@@ -72,7 +72,7 @@ public void RuleParse_ParseSingleRuleWithSingleCondition()
pattern: "article.aspx?id={R:1}&title={R:2}"));
// act
- var res = new UrlRewriteFileParser().Parse(new StringReader(xml));
+ var res = new UrlRewriteFileParser().Parse(new StringReader(xml), false);
// assert
AssertUrlRewriteRuleEquality(expected, res);
@@ -121,7 +121,7 @@ public void RuleParse_ParseMultipleRules()
pattern: "article.aspx?id={R:1}&title={R:2}"));
// act
- var res = new UrlRewriteFileParser().Parse(new StringReader(xml));
+ var res = new UrlRewriteFileParser().Parse(new StringReader(xml), false);
// assert
AssertUrlRewriteRuleEquality(expected, res);
@@ -150,7 +150,7 @@ public void Should_parse_global_rules()
";
// act
- var rules = new UrlRewriteFileParser().Parse(new StringReader(xml));
+ var rules = new UrlRewriteFileParser().Parse(new StringReader(xml), false);
// assert
Assert.Equal(2, rules.Count);
@@ -219,4 +219,4 @@ private void AssertUrlRewriteRuleEquality(IList actual, IList
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Middleware/Rewrite/test/IISUrlRewrite/FormatExceptionHandlingTests.cs b/src/Middleware/Rewrite/test/IISUrlRewrite/FormatExceptionHandlingTests.cs
index f6771dddfed0..20ad022d5afa 100644
--- a/src/Middleware/Rewrite/test/IISUrlRewrite/FormatExceptionHandlingTests.cs
+++ b/src/Middleware/Rewrite/test/IISUrlRewrite/FormatExceptionHandlingTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// 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;
@@ -63,8 +63,8 @@ public class FormatExceptionHandlingTests
public void ThrowFormatExceptionWithCorrectMessage(string input, string expected)
{
// Arrange, Act, Assert
- var ex = Assert.Throws(() => new UrlRewriteFileParser().Parse(new StringReader(input)));
+ var ex = Assert.Throws(() => new UrlRewriteFileParser().Parse(new StringReader(input), false));
Assert.Equal(expected, ex.Message);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Middleware/Rewrite/test/IISUrlRewrite/InputParserTests.cs b/src/Middleware/Rewrite/test/IISUrlRewrite/InputParserTests.cs
index ebc32becdc29..0439bc4fa0f9 100644
--- a/src/Middleware/Rewrite/test/IISUrlRewrite/InputParserTests.cs
+++ b/src/Middleware/Rewrite/test/IISUrlRewrite/InputParserTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// 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;
@@ -94,7 +94,7 @@ public void FormatExceptionsOnBadSyntax(string testString)
[Fact]
public void Should_throw_FormatException_if_no_rewrite_maps_are_defined()
{
- Assert.Throws(() => new InputParser(null).ParseInputString("{apiMap:{R:1}}", UriMatchPart.Path));
+ Assert.Throws(() => new InputParser(null, false).ParseInputString("{apiMap:{R:1}}", UriMatchPart.Path));
}
[Fact]
@@ -104,7 +104,7 @@ public void Should_throw_FormatException_if_rewrite_map_not_found()
const string undefinedMapName = "apiMap";
var map = new IISRewriteMap(definedMapName);
var maps = new IISRewriteMapCollection { map };
- Assert.Throws(() => new InputParser(maps).ParseInputString($"{{{undefinedMapName}:{{R:1}}}}", UriMatchPart.Path));
+ Assert.Throws(() => new InputParser(maps, false).ParseInputString($"{{{undefinedMapName}:{{R:1}}}}", UriMatchPart.Path));
}
[Fact]
@@ -118,7 +118,7 @@ public void Should_parse_RewriteMapSegment_and_successfully_evaluate_result()
var maps = new IISRewriteMapCollection { map };
var inputString = $"{{{expectedMapName}:{{R:1}}}}";
- var pattern = new InputParser(maps).ParseInputString(inputString, UriMatchPart.Path);
+ var pattern = new InputParser(maps, false).ParseInputString(inputString, UriMatchPart.Path);
Assert.Equal(1, pattern.PatternSegments.Count);
var segment = pattern.PatternSegments.Single();
diff --git a/src/Middleware/Rewrite/test/IISUrlRewrite/InvalidUrlRewriteFormatExceptionHandlingTests.cs b/src/Middleware/Rewrite/test/IISUrlRewrite/InvalidUrlRewriteFormatExceptionHandlingTests.cs
index 5c2e26fc5ff0..f144104a67fe 100644
--- a/src/Middleware/Rewrite/test/IISUrlRewrite/InvalidUrlRewriteFormatExceptionHandlingTests.cs
+++ b/src/Middleware/Rewrite/test/IISUrlRewrite/InvalidUrlRewriteFormatExceptionHandlingTests.cs
@@ -211,8 +211,8 @@ public class InvalidUrlRewriteFormatExceptionHandlingTests
public void ThrowInvalidUrlRewriteFormatExceptionWithCorrectMessage(string input, string expected)
{
// Arrange, Act, Assert
- var ex = Assert.Throws(() => new UrlRewriteFileParser().Parse(new StringReader(input)));
+ var ex = Assert.Throws(() => new UrlRewriteFileParser().Parse(new StringReader(input), false));
Assert.Equal(expected, ex.Message);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Middleware/Rewrite/test/IISUrlRewrite/ServerVariableTests.cs b/src/Middleware/Rewrite/test/IISUrlRewrite/ServerVariableTests.cs
index b56a8c78548f..274ef848e5e8 100644
--- a/src/Middleware/Rewrite/test/IISUrlRewrite/ServerVariableTests.cs
+++ b/src/Middleware/Rewrite/test/IISUrlRewrite/ServerVariableTests.cs
@@ -1,14 +1,16 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+using System.Collections.Generic;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Rewrite.Internal;
using Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;
using Microsoft.Net.Http.Headers;
using Xunit;
-namespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite
+namespace Microsoft.AspNetCore.Rewrite.Tests.IISUrlRewrite
{
public class ServerVariableTests
{
@@ -32,13 +34,105 @@ public void CheckServerVariableParsingAndApplication(string variable, string exp
{
// Arrange and Act
var testParserContext = new ParserContext("test");
- var serverVar = ServerVariables.FindServerVariable(variable, testParserContext, uriMatchPart);
- var lookup = serverVar.Evaluate(CreateTestHttpContext(), CreateTestRuleMatch().BackReferences, CreateTestCondMatch().BackReferences);
+ var serverVar = ServerVariables.FindServerVariable(variable, testParserContext, uriMatchPart, true);
+ var lookup = serverVar.Evaluate(CreateTestRewriteContext(), CreateTestRuleMatch().BackReferences, CreateTestCondMatch().BackReferences);
// Assert
Assert.Equal(expected, lookup);
}
- private RewriteContext CreateTestHttpContext()
+ [Theory]
+ [InlineData("CONTENT_LENGTH", "20", UriMatchPart.Path)]
+ [InlineData("CONTENT_TYPE", "text/xml", UriMatchPart.Path)]
+ [InlineData("HTTP_ACCEPT", "other-accept", UriMatchPart.Path)]
+ [InlineData("HTTP_COOKIE", "other-cookie", UriMatchPart.Path)]
+ [InlineData("HTTP_HOST", "otherexample.com", UriMatchPart.Path)]
+ [InlineData("HTTP_REFERER", "other-referer", UriMatchPart.Path)]
+ [InlineData("HTTP_USER_AGENT", "other-useragent", UriMatchPart.Path)]
+ [InlineData("HTTP_CONNECTION", "other-connection", UriMatchPart.Path)]
+ [InlineData("HTTP_URL", "http://otherexample.com/other-foo?bar=2", UriMatchPart.Full)]
+ [InlineData("HTTP_URL", "http://otherexample.com/other-foo?bar=2", UriMatchPart.Path)]
+ [InlineData("QUERY_STRING", "bar=2", UriMatchPart.Path)]
+ [InlineData("REQUEST_FILENAME", "/other-foo", UriMatchPart.Path)]
+ [InlineData("REQUEST_URI", "/other-foo", UriMatchPart.Path)]
+ [InlineData("REQUEST_URI", "/other-foo", UriMatchPart.Full)]
+ [InlineData("REQUEST_METHOD", "POST", UriMatchPart.Full)]
+ public void CheckServerVariableFeatureHasPrecedenceWhenEnabled(string variable, string expected, UriMatchPart uriMatchPart)
+ {
+ // Arrange and Act
+ var testParserContext = new ParserContext("test");
+ var serverVar = ServerVariables.FindServerVariable(variable, testParserContext, uriMatchPart, false);
+ var httpContext = CreateTestHttpContext();
+ httpContext.Features.Set(new TestServerVariablesFeature(new Dictionary
+ {
+ ["CONTENT_LENGTH"] = "20",
+ ["CONTENT_TYPE"] = "text/xml",
+ ["HTTP_ACCEPT"] = "other-accept",
+ ["HTTP_COOKIE"] = "other-cookie",
+ ["HTTP_HOST"] = "otherexample.com",
+ ["HTTP_REFERER"] = "other-referer",
+ ["HTTP_USER_AGENT"] = "other-useragent",
+ ["HTTP_CONNECTION"] = "other-connection",
+ ["HTTP_URL"] = "http://otherexample.com/other-foo?bar=2",
+ ["QUERY_STRING"] = "bar=2",
+ ["REQUEST_FILENAME"] = "/other-foo",
+ ["REQUEST_URI"] = "/other-foo",
+ ["REQUEST_METHOD"] = "POST"
+ }));
+
+ var rewriteContext = CreateTestRewriteContext(httpContext);
+ var lookup = serverVar.Evaluate(rewriteContext, CreateTestRuleMatch().BackReferences, CreateTestCondMatch().BackReferences);
+
+ // Assert
+ Assert.Equal(expected, lookup);
+ }
+
+ [Theory]
+ [InlineData("CONTENT_LENGTH", "10", UriMatchPart.Path)]
+ [InlineData("CONTENT_TYPE", "json", UriMatchPart.Path)]
+ [InlineData("HTTP_ACCEPT", "accept", UriMatchPart.Path)]
+ [InlineData("HTTP_COOKIE", "cookie", UriMatchPart.Path)]
+ [InlineData("HTTP_HOST", "example.com", UriMatchPart.Path)]
+ [InlineData("HTTP_REFERER", "referer", UriMatchPart.Path)]
+ [InlineData("HTTP_USER_AGENT", "useragent", UriMatchPart.Path)]
+ [InlineData("HTTP_CONNECTION", "connection", UriMatchPart.Path)]
+ [InlineData("HTTP_URL", "/foo", UriMatchPart.Path)]
+ [InlineData("HTTP_URL", "http://example.com/foo?bar=1", UriMatchPart.Full)]
+ [InlineData("QUERY_STRING", "bar=1", UriMatchPart.Path)]
+ [InlineData("REQUEST_FILENAME", "/foo", UriMatchPart.Path)]
+ [InlineData("REQUEST_URI", "/foo", UriMatchPart.Path)]
+ [InlineData("REQUEST_URI", "http://example.com/foo?bar=1", UriMatchPart.Full)]
+ [InlineData("REQUEST_METHOD", "GET", UriMatchPart.Full)]
+ public void CheckServerVariableFeatureIsntUsedWhenDisabled(string variable, string expected, UriMatchPart uriMatchPart)
+ {
+ // Arrange and Act
+ var testParserContext = new ParserContext("test");
+ var serverVar = ServerVariables.FindServerVariable(variable, testParserContext, uriMatchPart, true);
+ var httpContext = CreateTestHttpContext();
+ httpContext.Features.Set(new TestServerVariablesFeature(new Dictionary
+ {
+ ["CONTENT_LENGTH"] = "20",
+ ["CONTENT_TYPE"] = "text/xml",
+ ["HTTP_ACCEPT"] = "other-accept",
+ ["HTTP_COOKIE"] = "other-cookie",
+ ["HTTP_HOST"] = "otherexample.com",
+ ["HTTP_REFERER"] = "other-referer",
+ ["HTTP_USER_AGENT"] = "other-useragent",
+ ["HTTP_CONNECTION"] = "other-connection",
+ ["HTTP_URL"] = "http://otherexample.com/other-foo?bar=2",
+ ["QUERY_STRING"] = "bar=2",
+ ["REQUEST_FILENAME"] = "/other-foo",
+ ["REQUEST_URI"] = "/other-foo",
+ ["REQUEST_METHOD"] = "POST"
+ }));
+
+ var rewriteContext = CreateTestRewriteContext(httpContext);
+ var lookup = serverVar.Evaluate(rewriteContext, CreateTestRuleMatch().BackReferences, CreateTestCondMatch().BackReferences);
+
+ // Assert
+ Assert.Equal(expected, lookup);
+ }
+
+ private HttpContext CreateTestHttpContext()
{
var context = new DefaultHttpContext();
context.Request.Method = HttpMethods.Get;
@@ -53,7 +147,13 @@ private RewriteContext CreateTestHttpContext()
context.Request.Headers[HeaderNames.Referer] = "referer";
context.Request.Headers[HeaderNames.UserAgent] = "useragent";
context.Request.Headers[HeaderNames.Connection] = "connection";
- return new RewriteContext { HttpContext = context };
+
+ return context;
+ }
+
+ private RewriteContext CreateTestRewriteContext(HttpContext context = null)
+ {
+ return new RewriteContext { HttpContext = context ?? CreateTestHttpContext() };
}
private MatchResults CreateTestRuleMatch()
@@ -74,7 +174,7 @@ private void EmptyQueryStringCheck()
var context = new DefaultHttpContext();
var rewriteContext = new RewriteContext { HttpContext = context };
var testParserContext = new ParserContext("test");
- var serverVar = ServerVariables.FindServerVariable("QUERY_STRING", testParserContext, UriMatchPart.Path);
+ var serverVar = ServerVariables.FindServerVariable("QUERY_STRING", testParserContext, UriMatchPart.Path, true);
var lookup = serverVar.Evaluate(rewriteContext, CreateTestRuleMatch().BackReferences, CreateTestCondMatch().BackReferences);
Assert.Equal(string.Empty, lookup);
diff --git a/src/Middleware/Rewrite/test/IISUrlRewrite/TestServerVariablesFeature.cs b/src/Middleware/Rewrite/test/IISUrlRewrite/TestServerVariablesFeature.cs
new file mode 100644
index 000000000000..372039679ada
--- /dev/null
+++ b/src/Middleware/Rewrite/test/IISUrlRewrite/TestServerVariablesFeature.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.
+
+using System.Collections.Generic;
+using Microsoft.AspNetCore.Http.Features;
+
+namespace Microsoft.AspNetCore.Rewrite.Tests.IISUrlRewrite
+{
+ public class TestServerVariablesFeature : IServerVariablesFeature
+ {
+ private readonly Dictionary _variables;
+
+ public TestServerVariablesFeature(Dictionary variables)
+ {
+ _variables = variables;
+ }
+
+ public string this[string variableName]
+ {
+ get => _variables[variableName];
+ set => _variables[variableName] = value;
+ }
+ }
+}
diff --git a/src/Middleware/Rewrite/test/IISUrlRewrite/UrlRewriteApplicationTests.cs b/src/Middleware/Rewrite/test/IISUrlRewrite/UrlRewriteApplicationTests.cs
index ecc753a620c5..d1b9a83936cc 100644
--- a/src/Middleware/Rewrite/test/IISUrlRewrite/UrlRewriteApplicationTests.cs
+++ b/src/Middleware/Rewrite/test/IISUrlRewrite/UrlRewriteApplicationTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// 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;
@@ -23,7 +23,7 @@ public void ApplyRule_AssertStopProcessingFlagWillTerminateOnNoAction()
");
- var rules = new UrlRewriteFileParser().Parse(xml);
+ var rules = new UrlRewriteFileParser().Parse(xml, false);
Assert.Equal(1, rules.Count);
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
@@ -42,7 +42,7 @@ public void ApplyRule_AssertNoTerminateFlagWillNotTerminateOnNoAction()
");
- var rules = new UrlRewriteFileParser().Parse(xml);
+ var rules = new UrlRewriteFileParser().Parse(xml, false);
Assert.Equal(1, rules.Count);
var context = new RewriteContext { HttpContext = new DefaultHttpContext() };
@@ -64,7 +64,7 @@ public void ApplyRule_TrackAllCaptures()
");
- var rules = new UrlRewriteFileParser().Parse(xml);
+ var rules = new UrlRewriteFileParser().Parse(xml, false);
Assert.Equal(1, rules.Count);
Assert.True(rules[0].Conditions.TrackAllCaptures);