Improvements for IEndpointSelectorPolicy
These changes are based on our discussion earlier this week. Adding async, and making it possible to short circuit, which should be better aligned with the requirments of versioning.
This commit is contained in:
parent
e90e670ac8
commit
a0aa61fd10
|
|
@ -24,16 +24,30 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
_selectorPolicies = matcherPolicies.OrderBy(p => p.Order).OfType<IEndpointSelectorPolicy>().ToArray();
|
||||
}
|
||||
|
||||
public override Task SelectAsync(
|
||||
public override async Task SelectAsync(
|
||||
HttpContext httpContext,
|
||||
EndpointFeature feature,
|
||||
CandidateSet candidateSet)
|
||||
{
|
||||
var selectorPolicies = _selectorPolicies;
|
||||
for (var i = 0; i < _selectorPolicies.Length; i++)
|
||||
{
|
||||
_selectorPolicies[i].Apply(httpContext, candidateSet);
|
||||
await selectorPolicies[i].ApplyAsync(httpContext, feature, candidateSet);
|
||||
if (feature.Endpoint != null)
|
||||
{
|
||||
// This is a short circuit, the selector chose an endpoint.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessFinalCandidates(httpContext, feature, candidateSet);
|
||||
}
|
||||
|
||||
private static void ProcessFinalCandidates(
|
||||
HttpContext httpContext,
|
||||
EndpointFeature feature,
|
||||
CandidateSet candidateSet)
|
||||
{
|
||||
RouteEndpoint endpoint = null;
|
||||
RouteValueDictionary values = null;
|
||||
int? foundScore = null;
|
||||
|
|
@ -76,8 +90,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
feature.Endpoint = endpoint;
|
||||
feature.RouteValues = values;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static void ReportAmbiguity(CandidateSet candidates)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Matching
|
||||
{
|
||||
|
|
@ -19,12 +20,21 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
/// <param name="httpContext">
|
||||
/// The <see cref="HttpContext"/> associated with the current request.
|
||||
/// </param>
|
||||
/// <param name="feature">
|
||||
/// The <see cref="EndpointFeature"/> associated with the current request.
|
||||
/// </param>
|
||||
/// <param name="candidates">The <see cref="CandidateSet"/>.</param>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Implementations of <see cref="IEndpointSelectorPolicy"/> should implement this method
|
||||
/// and filter the set of candidates in the <paramref name="candidates"/> by setting
|
||||
/// <see cref="CandidateState.IsValidCandidate"/> to <c>false</c> where desired.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// To signal an error condition, set <see cref="EndpointFeature.Endpoint"/> to an
|
||||
/// <see cref="Endpoint"/> value that will produce the desired error when executed.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
void Apply(HttpContext httpContext, CandidateSet candidates);
|
||||
Task ApplyAsync(HttpContext httpContext, EndpointFeature feature, CandidateSet candidates);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +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.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
|
@ -184,10 +185,11 @@ test: /test3", ex.Message);
|
|||
var policy = new Mock<MatcherPolicy>();
|
||||
policy
|
||||
.As<IEndpointSelectorPolicy>()
|
||||
.Setup(p => p.Apply(It.IsAny<HttpContext>(), It.IsAny<CandidateSet>()))
|
||||
.Callback<HttpContext, CandidateSet>((c, cs) =>
|
||||
.Setup(p => p.ApplyAsync(It.IsAny<HttpContext>(), It.IsAny<EndpointFeature>(), It.IsAny<CandidateSet>()))
|
||||
.Returns<HttpContext, EndpointFeature, CandidateSet>((c, f, cs) =>
|
||||
{
|
||||
cs[1].IsValidCandidate = false;
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
||||
candidateSet[0].IsValidCandidate = false;
|
||||
|
|
@ -204,6 +206,48 @@ test: /test3", ex.Message);
|
|||
Assert.Same(endpoints[2], feature.Endpoint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SelectAsync_RunsEndpointSelectorPolicies_CanShortCircuit()
|
||||
{
|
||||
// Arrange
|
||||
var endpoints = new RouteEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), CreateEndpoint("/test3"), };
|
||||
var scores = new int[] { 0, 0, 1 };
|
||||
var candidateSet = CreateCandidateSet(endpoints, scores);
|
||||
|
||||
var policy1 = new Mock<MatcherPolicy>();
|
||||
policy1
|
||||
.As<IEndpointSelectorPolicy>()
|
||||
.Setup(p => p.ApplyAsync(It.IsAny<HttpContext>(), It.IsAny<EndpointFeature>(), It.IsAny<CandidateSet>()))
|
||||
.Returns<HttpContext, EndpointFeature, CandidateSet>((c, f, cs) =>
|
||||
{
|
||||
f.Endpoint = cs[0].Endpoint;
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
||||
// This should never run, it's after policy1 which short circuits
|
||||
var policy2 = new Mock<MatcherPolicy>();
|
||||
policy2
|
||||
.SetupGet(p => p.Order)
|
||||
.Returns(1000);
|
||||
policy2
|
||||
.As<IEndpointSelectorPolicy>()
|
||||
.Setup(p => p.ApplyAsync(It.IsAny<HttpContext>(), It.IsAny<EndpointFeature>(), It.IsAny<CandidateSet>()))
|
||||
.Throws(new InvalidOperationException());
|
||||
|
||||
candidateSet[0].IsValidCandidate = false;
|
||||
candidateSet[1].IsValidCandidate = true;
|
||||
candidateSet[2].IsValidCandidate = true;
|
||||
|
||||
var (httpContext, feature) = CreateContext();
|
||||
var selector = CreateSelector(policy1.Object, policy2.Object);
|
||||
|
||||
// Act
|
||||
await selector.SelectAsync(httpContext, feature, candidateSet);
|
||||
|
||||
// Assert
|
||||
Assert.Same(endpoints[0], feature.Endpoint);
|
||||
}
|
||||
|
||||
private static (HttpContext httpContext, EndpointFeature feature) CreateContext()
|
||||
{
|
||||
var feature = new EndpointFeature();
|
||||
|
|
|
|||
Loading…
Reference in New Issue