Fix endpoint routing statefulness.
- In the case that other middleware change the path of an `HttpContext` and cause middleware to re-invoke we used to short-circuit on second time through the middleware pipeline, now we allow routing to occur. - Added unit tests to validate the clearing of state. #11233
This commit is contained in:
parent
ec81582dff
commit
9a6881b0e8
|
|
@ -51,6 +51,8 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
if (endpoint != null)
|
if (endpoint != null)
|
||||||
{
|
{
|
||||||
Log.MatchSkipped(_logger, endpoint);
|
Log.MatchSkipped(_logger, endpoint);
|
||||||
|
|
||||||
|
// Someone else set the endpoint, we'll let them handle the unsetting.
|
||||||
return _next(httpContext);
|
return _next(httpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,7 +89,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private Task SetRoutingAndContinue(HttpContext httpContext)
|
private async Task SetRoutingAndContinue(HttpContext httpContext)
|
||||||
{
|
{
|
||||||
// If there was no mutation of the endpoint then log failure
|
// If there was no mutation of the endpoint then log failure
|
||||||
var endpoint = httpContext.GetEndpoint();
|
var endpoint = httpContext.GetEndpoint();
|
||||||
|
|
@ -107,7 +109,16 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
Log.MatchSuccess(_logger, endpoint);
|
Log.MatchSuccess(_logger, endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _next(httpContext);
|
try
|
||||||
|
{
|
||||||
|
await _next(httpContext);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// We unset the endpoint after calling through to the next middleware. This enables any future calls into
|
||||||
|
// endpoint routing don't no-op from there already being an endpoint set.
|
||||||
|
httpContext.SetEndpoint(endpoint: null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialization is async to avoid blocking threads while reflection and things
|
// Initialization is async to avoid blocking threads while reflection and things
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,30 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
public class EndpointRoutingMiddlewareTest
|
public class EndpointRoutingMiddlewareTest
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Invoke_OnCall_SetsEndpointFeature()
|
public async Task Invoke_OnException_ResetsEndpoint()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var httpContext = CreateHttpContext();
|
||||||
|
|
||||||
|
var middleware = CreateMiddleware(next: context => throw new Exception());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await middleware.Invoke(httpContext);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Do nothing, we expect the test to throw.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var endpoint = httpContext.GetEndpoint();
|
||||||
|
Assert.Null(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_OnCall_SetsEndpointFeatureAndResetsEndpoint()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var httpContext = CreateHttpContext();
|
var httpContext = CreateHttpContext();
|
||||||
|
|
@ -34,14 +57,16 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
// Assert
|
// Assert
|
||||||
var endpointFeature = httpContext.Features.Get<IEndpointFeature>();
|
var endpointFeature = httpContext.Features.Get<IEndpointFeature>();
|
||||||
Assert.NotNull(endpointFeature);
|
Assert.NotNull(endpointFeature);
|
||||||
|
Assert.Null(endpointFeature.Endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Invoke_SkipsRouting_IfEndpointSet()
|
public async Task Invoke_SkipsRoutingAndMaintainsEndpoint_IfEndpointSet()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var httpContext = CreateHttpContext();
|
var httpContext = CreateHttpContext();
|
||||||
httpContext.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(), "myapp"));
|
var expectedEndpoint = new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(), "myapp");
|
||||||
|
httpContext.SetEndpoint(expectedEndpoint);
|
||||||
|
|
||||||
var middleware = CreateMiddleware();
|
var middleware = CreateMiddleware();
|
||||||
|
|
||||||
|
|
@ -50,7 +75,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var endpoint = httpContext.GetEndpoint();
|
var endpoint = httpContext.GetEndpoint();
|
||||||
Assert.NotNull(endpoint);
|
Assert.Same(expectedEndpoint, endpoint);
|
||||||
Assert.Equal("myapp", endpoint.DisplayName);
|
Assert.Equal("myapp", endpoint.DisplayName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue