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 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, 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 public static partial class MapWhenExtensions
{ {
@ -67,6 +68,7 @@ namespace Microsoft.AspNetCore.Builder.Extensions
public MapOptions() { } public MapOptions() { }
public Microsoft.AspNetCore.Http.RequestDelegate Branch { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } 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 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 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> /// <param name="configuration">The branch to take for positive path matches.</param>
/// <returns>The <see cref="IApplicationBuilder"/> instance.</returns> /// <returns>The <see cref="IApplicationBuilder"/> instance.</returns>
public static IApplicationBuilder Map(this IApplicationBuilder app, PathString pathMatch, Action<IApplicationBuilder> configuration) 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) if (app == null)
{ {
@ -46,6 +60,7 @@ namespace Microsoft.AspNetCore.Builder
{ {
Branch = branch, Branch = branch,
PathMatch = pathMatch, PathMatch = pathMatch,
PreserveMatchedPathSegment = preserveMatchedPathSegment
}; };
return app.Use(next => new MapMiddleware(next, options).Invoke); 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)); throw new ArgumentNullException(nameof(context));
} }
PathString matchedPath; if (context.Request.Path.StartsWithSegments(_options.PathMatch, out var matchedPath, out var remainingPath))
PathString remainingPath;
if (context.Request.Path.StartsWithSegments(_options.PathMatch, out matchedPath, out remainingPath))
{ {
// Update the path
var path = context.Request.Path; var path = context.Request.Path;
var pathBase = context.Request.PathBase; 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 try
{ {
@ -65,8 +66,11 @@ namespace Microsoft.AspNetCore.Builder.Extensions
} }
finally finally
{ {
context.Request.PathBase = pathBase; if (!_options.PreserveMatchedPathSegment)
context.Request.Path = path; {
context.Request.PathBase = pathBase;
context.Request.Path = path;
}
} }
} }
else else

View File

@ -19,5 +19,11 @@ namespace Microsoft.AspNetCore.Builder.Extensions
/// The branch taken for a positive match. /// The branch taken for a positive match.
/// </summary> /// </summary>
public RequestDelegate Branch { get; set; } 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"]); 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] [Theory]
[InlineData("/")] [InlineData("/")]
[InlineData("/foo/")] [InlineData("/foo/")]