Add PreserveMatchedPathSegment to MapOptions #3762 (#15364)

This commit is contained in:
Kahbazi 2019-10-28 19:21:30 +03:30 committed by Chris Ross
parent c376e833e4
commit 3a92c93cfb
5 changed files with 67 additions and 12 deletions

View File

@ -27,6 +27,7 @@ namespace Microsoft.AspNetCore.Builder
public static partial class MapExtensions
{
public static Microsoft.AspNetCore.Builder.IApplicationBuilder Map(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Http.PathString pathMatch, System.Action<Microsoft.AspNetCore.Builder.IApplicationBuilder> configuration) { throw null; }
public static Microsoft.AspNetCore.Builder.IApplicationBuilder Map(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Http.PathString pathMatch, bool preserveMatchedPathSegment, System.Action<Microsoft.AspNetCore.Builder.IApplicationBuilder> configuration) { throw null; }
}
public static partial class MapWhenExtensions
{
@ -67,6 +68,7 @@ namespace Microsoft.AspNetCore.Builder.Extensions
public MapOptions() { }
public Microsoft.AspNetCore.Http.RequestDelegate Branch { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public Microsoft.AspNetCore.Http.PathString PathMatch { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public bool PreserveMatchedPathSegment { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
}
public partial class MapWhenMiddleware
{

View File

@ -21,6 +21,20 @@ namespace Microsoft.AspNetCore.Builder
/// <param name="configuration">The branch to take for positive path matches.</param>
/// <returns>The <see cref="IApplicationBuilder"/> instance.</returns>
public static IApplicationBuilder Map(this IApplicationBuilder app, PathString pathMatch, Action<IApplicationBuilder> configuration)
{
return Map(app, pathMatch, preserveMatchedPathSegment: false, configuration);
}
/// <summary>
/// Branches the request pipeline based on matches of the given request path. If the request path starts with
/// the given path, the branch is executed.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> instance.</param>
/// <param name="pathMatch">The request path to match.</param>
/// <param name="preserveMatchedPathSegment">if false, matched path would be removed from Request.Path and added to Request.PathBase.</param>
/// <param name="configuration">The branch to take for positive path matches.</param>
/// <returns>The <see cref="IApplicationBuilder"/> instance.</returns>
public static IApplicationBuilder Map(this IApplicationBuilder app, PathString pathMatch, bool preserveMatchedPathSegment, Action<IApplicationBuilder> configuration)
{
if (app == null)
{
@ -46,8 +60,9 @@ namespace Microsoft.AspNetCore.Builder
{
Branch = branch,
PathMatch = pathMatch,
PreserveMatchedPathSegment = preserveMatchedPathSegment
};
return app.Use(next => new MapMiddleware(next, options).Invoke);
}
}
}
}

View File

@ -48,16 +48,17 @@ namespace Microsoft.AspNetCore.Builder.Extensions
throw new ArgumentNullException(nameof(context));
}
PathString matchedPath;
PathString remainingPath;
if (context.Request.Path.StartsWithSegments(_options.PathMatch, out matchedPath, out remainingPath))
if (context.Request.Path.StartsWithSegments(_options.PathMatch, out var matchedPath, out var remainingPath))
{
// Update the path
var path = context.Request.Path;
var pathBase = context.Request.PathBase;
context.Request.PathBase = pathBase.Add(matchedPath);
context.Request.Path = remainingPath;
if (!_options.PreserveMatchedPathSegment)
{
// Update the path
context.Request.PathBase = pathBase.Add(matchedPath);
context.Request.Path = remainingPath;
}
try
{
@ -65,8 +66,11 @@ namespace Microsoft.AspNetCore.Builder.Extensions
}
finally
{
context.Request.PathBase = pathBase;
context.Request.Path = path;
if (!_options.PreserveMatchedPathSegment)
{
context.Request.PathBase = pathBase;
context.Request.Path = path;
}
}
}
else
@ -75,4 +79,4 @@ namespace Microsoft.AspNetCore.Builder.Extensions
}
}
}
}
}

View File

@ -19,5 +19,11 @@ namespace Microsoft.AspNetCore.Builder.Extensions
/// The branch taken for a positive match.
/// </summary>
public RequestDelegate Branch { get; set; }
/// <summary>
/// If false, matched path would be removed from Request.Path and added to Request.PathBase
/// Defaults to false.
/// </summary>
public bool PreserveMatchedPathSegment { get; set; }
}
}
}

View File

@ -95,6 +95,34 @@ namespace Microsoft.AspNetCore.Builder.Extensions
Assert.Equal(requestPath.Substring(matchPath.Length), context.Items["test.Path"]);
}
[Theory]
[InlineData("/foo", "", "/foo")]
[InlineData("/foo", "", "/foo/")]
[InlineData("/foo", "/Bar", "/foo")]
[InlineData("/foo", "/Bar", "/foo/cho")]
[InlineData("/foo", "/Bar", "/foo/cho/")]
[InlineData("/foo/cho", "/Bar", "/foo/cho")]
[InlineData("/foo/cho", "/Bar", "/foo/cho/do")]
[InlineData("/foo", "", "/Foo")]
[InlineData("/foo", "", "/Foo/")]
[InlineData("/foo", "/Bar", "/Foo")]
[InlineData("/foo", "/Bar", "/Foo/Cho")]
[InlineData("/foo", "/Bar", "/Foo/Cho/")]
[InlineData("/foo/cho", "/Bar", "/Foo/Cho")]
[InlineData("/foo/cho", "/Bar", "/Foo/Cho/do")]
public async Task PathMatchAction_BranchTaken_WithPreserveMatchedPathSegment(string matchPath, string basePath, string requestPath)
{
HttpContext context = CreateRequest(basePath, requestPath);
var builder = new ApplicationBuilder(serviceProvider: null);
builder.Map(matchPath, true, subBuilder => subBuilder.Run(Success));
var app = builder.Build();
await app.Invoke(context);
Assert.Equal(200, context.Response.StatusCode);
Assert.Equal(basePath, (string)context.Items["test.PathBase"]);
Assert.Equal(requestPath, context.Items["test.Path"]);
}
[Theory]
[InlineData("/")]
[InlineData("/foo/")]