Make endpoint selector policies per-candidate-set
This allows us to filter `IEndpointSelectorPolicy` instance based on whether the apply to a given candidate set. This should allow us to remove some HAXXX from MVC. The idea here is the ESP becomes much more pay-for-play if you can statically eliminate many of the cases where it would usually no op.
This commit is contained in:
parent
af47b27f0d
commit
9db2833fc2
|
|
@ -1,75 +0,0 @@
|
|||
// 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 BenchmarkDotNet.Attributes;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Matching
|
||||
{
|
||||
// Generated from https://github.com/Azure/azure-rest-api-specs
|
||||
public partial class MatcherFindCandidateSetAzureBenchmark : EndpointRoutingBenchmarkBase
|
||||
{
|
||||
// SegmentCount should be max-segments + 1, but we don't have a good way to compute
|
||||
// it here, so using 32 as a safe guess.
|
||||
private const int SegmentCount = 32;
|
||||
|
||||
private const int SampleCount = 100;
|
||||
|
||||
private BarebonesMatcher _baseline;
|
||||
private DfaMatcher _dfa;
|
||||
|
||||
private int[] _samples;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
SetupEndpoints();
|
||||
|
||||
SetupRequests();
|
||||
|
||||
// The perf is kinda slow for these benchmarks, so we do some sampling
|
||||
// of the request data.
|
||||
_samples = SampleRequests(EndpointCount, SampleCount);
|
||||
|
||||
_baseline = (BarebonesMatcher)SetupMatcher(new BarebonesMatcherBuilder());
|
||||
_dfa = (DfaMatcher)SetupMatcher(CreateDfaMatcherBuilder());
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true, OperationsPerInvoke = SampleCount)]
|
||||
public void Baseline()
|
||||
{
|
||||
for (var i = 0; i < SampleCount; i++)
|
||||
{
|
||||
var sample = _samples[i];
|
||||
var httpContext = Requests[sample];
|
||||
|
||||
var path = httpContext.Request.Path.Value;
|
||||
var segments = new ReadOnlySpan<PathSegment>(Array.Empty<PathSegment>());
|
||||
|
||||
var candidates = _baseline.Matchers[sample].FindCandidateSet(path, segments);
|
||||
|
||||
var endpoint = candidates[0].Endpoint;
|
||||
Validate(httpContext, Endpoints[sample], endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(OperationsPerInvoke = SampleCount)]
|
||||
public void Dfa()
|
||||
{
|
||||
for (var i = 0; i < SampleCount; i++)
|
||||
{
|
||||
var sample = _samples[i];
|
||||
var httpContext = Requests[sample];
|
||||
|
||||
var path = httpContext.Request.Path.Value;
|
||||
Span<PathSegment> segments = stackalloc PathSegment[SegmentCount];
|
||||
var count = FastPathTokenizer.Tokenize(path, segments);
|
||||
|
||||
var candidates = _dfa.FindCandidateSet(httpContext, path, segments.Slice(0, count));
|
||||
|
||||
var endpoint = candidates[0].Endpoint;
|
||||
Validate(httpContext, Endpoints[sample], endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,67 +0,0 @@
|
|||
// 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 BenchmarkDotNet.Attributes;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Matching
|
||||
{
|
||||
// Generated from https://github.com/APIs-guru/openapi-directory
|
||||
// Use https://editor2.swagger.io/ to convert from yaml to json-
|
||||
public partial class MatcherFindCandidateSetGithubBenchmark : EndpointRoutingBenchmarkBase
|
||||
{
|
||||
// SegmentCount should be max-segments + 1, but we don't have a good way to compute
|
||||
// it here, so using 32 as a safe guess.
|
||||
private const int SegmentCount = 32;
|
||||
|
||||
private BarebonesMatcher _baseline;
|
||||
private DfaMatcher _dfa;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
SetupEndpoints();
|
||||
|
||||
SetupRequests();
|
||||
|
||||
_baseline = (BarebonesMatcher)SetupMatcher(new BarebonesMatcherBuilder());
|
||||
_dfa = (DfaMatcher)SetupMatcher(CreateDfaMatcherBuilder());
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true, OperationsPerInvoke = EndpointCount)]
|
||||
public void Baseline()
|
||||
{
|
||||
for (var i = 0; i < EndpointCount; i++)
|
||||
{
|
||||
var httpContext = Requests[i];
|
||||
|
||||
var path = httpContext.Request.Path.Value;
|
||||
var segments = new ReadOnlySpan<PathSegment>(Array.Empty<PathSegment>());
|
||||
|
||||
var candidates = _baseline.Matchers[i].FindCandidateSet(path, segments);
|
||||
|
||||
var endpoint = candidates[0].Endpoint;
|
||||
Validate(httpContext, Endpoints[i], endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark( OperationsPerInvoke = EndpointCount)]
|
||||
public void Dfa()
|
||||
{
|
||||
for (var i = 0; i < EndpointCount; i++)
|
||||
{
|
||||
var httpContext = Requests[i];
|
||||
|
||||
var path = httpContext.Request.Path.Value;
|
||||
Span<PathSegment> segments = stackalloc PathSegment[SegmentCount];
|
||||
var count = FastPathTokenizer.Tokenize(path, segments);
|
||||
|
||||
var candidates = _dfa.FindCandidateSet(httpContext, path, segments.Slice(0, count));
|
||||
|
||||
var endpoint = candidates[0].Endpoint;
|
||||
Validate(httpContext, Endpoints[i], endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,959 +0,0 @@
|
|||
|
||||
// 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 Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Matching
|
||||
{
|
||||
// This code was generated by the Swaggatherer
|
||||
public partial class MatcherFindCandidateSetGithubBenchmark : EndpointRoutingBenchmarkBase
|
||||
{
|
||||
private const int EndpointCount = 155;
|
||||
|
||||
private void SetupEndpoints()
|
||||
{
|
||||
Endpoints = new RouteEndpoint[155];
|
||||
Endpoints[0] = CreateEndpoint("/emojis");
|
||||
Endpoints[1] = CreateEndpoint("/events");
|
||||
Endpoints[2] = CreateEndpoint("/feeds");
|
||||
Endpoints[3] = CreateEndpoint("/gists");
|
||||
Endpoints[4] = CreateEndpoint("/issues");
|
||||
Endpoints[5] = CreateEndpoint("/markdown");
|
||||
Endpoints[6] = CreateEndpoint("/meta");
|
||||
Endpoints[7] = CreateEndpoint("/notifications");
|
||||
Endpoints[8] = CreateEndpoint("/rate_limit");
|
||||
Endpoints[9] = CreateEndpoint("/repositories");
|
||||
Endpoints[10] = CreateEndpoint("/user");
|
||||
Endpoints[11] = CreateEndpoint("/users");
|
||||
Endpoints[12] = CreateEndpoint("/gists/public");
|
||||
Endpoints[13] = CreateEndpoint("/gists/starred");
|
||||
Endpoints[14] = CreateEndpoint("/gitignore/templates");
|
||||
Endpoints[15] = CreateEndpoint("/markdown/raw");
|
||||
Endpoints[16] = CreateEndpoint("/search/code");
|
||||
Endpoints[17] = CreateEndpoint("/search/issues");
|
||||
Endpoints[18] = CreateEndpoint("/search/repositories");
|
||||
Endpoints[19] = CreateEndpoint("/search/users");
|
||||
Endpoints[20] = CreateEndpoint("/user/emails");
|
||||
Endpoints[21] = CreateEndpoint("/user/followers");
|
||||
Endpoints[22] = CreateEndpoint("/user/following");
|
||||
Endpoints[23] = CreateEndpoint("/user/issues");
|
||||
Endpoints[24] = CreateEndpoint("/user/keys");
|
||||
Endpoints[25] = CreateEndpoint("/user/orgs");
|
||||
Endpoints[26] = CreateEndpoint("/user/repos");
|
||||
Endpoints[27] = CreateEndpoint("/user/starred");
|
||||
Endpoints[28] = CreateEndpoint("/user/subscriptions");
|
||||
Endpoints[29] = CreateEndpoint("/user/teams");
|
||||
Endpoints[30] = CreateEndpoint("/legacy/repos/search/{keyword}");
|
||||
Endpoints[31] = CreateEndpoint("/legacy/user/email/{email}");
|
||||
Endpoints[32] = CreateEndpoint("/legacy/user/search/{keyword}");
|
||||
Endpoints[33] = CreateEndpoint("/legacy/issues/search/{owner}/{repository}/{state}/{keyword}");
|
||||
Endpoints[34] = CreateEndpoint("/gitignore/templates/{language}");
|
||||
Endpoints[35] = CreateEndpoint("/notifications/threads/{id}");
|
||||
Endpoints[36] = CreateEndpoint("/user/following/{username}");
|
||||
Endpoints[37] = CreateEndpoint("/user/keys/{keyId}");
|
||||
Endpoints[38] = CreateEndpoint("/notifications/threads/{id}/subscription");
|
||||
Endpoints[39] = CreateEndpoint("/user/starred/{owner}/{repo}");
|
||||
Endpoints[40] = CreateEndpoint("/user/subscriptions/{owner}/{repo}");
|
||||
Endpoints[41] = CreateEndpoint("/gists/{id}");
|
||||
Endpoints[42] = CreateEndpoint("/orgs/{org}");
|
||||
Endpoints[43] = CreateEndpoint("/teams/{teamId}");
|
||||
Endpoints[44] = CreateEndpoint("/users/{username}");
|
||||
Endpoints[45] = CreateEndpoint("/gists/{id}/comments");
|
||||
Endpoints[46] = CreateEndpoint("/gists/{id}/forks");
|
||||
Endpoints[47] = CreateEndpoint("/gists/{id}/star");
|
||||
Endpoints[48] = CreateEndpoint("/orgs/{org}/events");
|
||||
Endpoints[49] = CreateEndpoint("/orgs/{org}/issues");
|
||||
Endpoints[50] = CreateEndpoint("/orgs/{org}/members");
|
||||
Endpoints[51] = CreateEndpoint("/orgs/{org}/public_members");
|
||||
Endpoints[52] = CreateEndpoint("/orgs/{org}/repos");
|
||||
Endpoints[53] = CreateEndpoint("/orgs/{org}/teams");
|
||||
Endpoints[54] = CreateEndpoint("/teams/{teamId}/members");
|
||||
Endpoints[55] = CreateEndpoint("/teams/{teamId}/repos");
|
||||
Endpoints[56] = CreateEndpoint("/users/{username}/events");
|
||||
Endpoints[57] = CreateEndpoint("/users/{username}/followers");
|
||||
Endpoints[58] = CreateEndpoint("/users/{username}/gists");
|
||||
Endpoints[59] = CreateEndpoint("/users/{username}/keys");
|
||||
Endpoints[60] = CreateEndpoint("/users/{username}/orgs");
|
||||
Endpoints[61] = CreateEndpoint("/users/{username}/received_events");
|
||||
Endpoints[62] = CreateEndpoint("/users/{username}/repos");
|
||||
Endpoints[63] = CreateEndpoint("/users/{username}/starred");
|
||||
Endpoints[64] = CreateEndpoint("/users/{username}/subscriptions");
|
||||
Endpoints[65] = CreateEndpoint("/users/{username}/received_events/public");
|
||||
Endpoints[66] = CreateEndpoint("/users/{username}/events/orgs/{org}");
|
||||
Endpoints[67] = CreateEndpoint("/gists/{id}/comments/{commentId}");
|
||||
Endpoints[68] = CreateEndpoint("/orgs/{org}/members/{username}");
|
||||
Endpoints[69] = CreateEndpoint("/orgs/{org}/public_members/{username}");
|
||||
Endpoints[70] = CreateEndpoint("/teams/{teamId}/members/{username}");
|
||||
Endpoints[71] = CreateEndpoint("/teams/{teamId}/memberships/{username}");
|
||||
Endpoints[72] = CreateEndpoint("/users/{username}/following/{targetUser}");
|
||||
Endpoints[73] = CreateEndpoint("/teams/{teamId}/repos/{owner}/{repo}");
|
||||
Endpoints[74] = CreateEndpoint("/repos/{owner}/{repo}");
|
||||
Endpoints[75] = CreateEndpoint("/networks/{owner}/{repo}/events");
|
||||
Endpoints[76] = CreateEndpoint("/repos/{owner}/{repo}/assignees");
|
||||
Endpoints[77] = CreateEndpoint("/repos/{owner}/{repo}/branches");
|
||||
Endpoints[78] = CreateEndpoint("/repos/{owner}/{repo}/collaborators");
|
||||
Endpoints[79] = CreateEndpoint("/repos/{owner}/{repo}/comments");
|
||||
Endpoints[80] = CreateEndpoint("/repos/{owner}/{repo}/commits");
|
||||
Endpoints[81] = CreateEndpoint("/repos/{owner}/{repo}/contributors");
|
||||
Endpoints[82] = CreateEndpoint("/repos/{owner}/{repo}/deployments");
|
||||
Endpoints[83] = CreateEndpoint("/repos/{owner}/{repo}/downloads");
|
||||
Endpoints[84] = CreateEndpoint("/repos/{owner}/{repo}/events");
|
||||
Endpoints[85] = CreateEndpoint("/repos/{owner}/{repo}/forks");
|
||||
Endpoints[86] = CreateEndpoint("/repos/{owner}/{repo}/hooks");
|
||||
Endpoints[87] = CreateEndpoint("/repos/{owner}/{repo}/issues");
|
||||
Endpoints[88] = CreateEndpoint("/repos/{owner}/{repo}/keys");
|
||||
Endpoints[89] = CreateEndpoint("/repos/{owner}/{repo}/labels");
|
||||
Endpoints[90] = CreateEndpoint("/repos/{owner}/{repo}/languages");
|
||||
Endpoints[91] = CreateEndpoint("/repos/{owner}/{repo}/merges");
|
||||
Endpoints[92] = CreateEndpoint("/repos/{owner}/{repo}/milestones");
|
||||
Endpoints[93] = CreateEndpoint("/repos/{owner}/{repo}/notifications");
|
||||
Endpoints[94] = CreateEndpoint("/repos/{owner}/{repo}/pulls");
|
||||
Endpoints[95] = CreateEndpoint("/repos/{owner}/{repo}/readme");
|
||||
Endpoints[96] = CreateEndpoint("/repos/{owner}/{repo}/releases");
|
||||
Endpoints[97] = CreateEndpoint("/repos/{owner}/{repo}/stargazers");
|
||||
Endpoints[98] = CreateEndpoint("/repos/{owner}/{repo}/subscribers");
|
||||
Endpoints[99] = CreateEndpoint("/repos/{owner}/{repo}/subscription");
|
||||
Endpoints[100] = CreateEndpoint("/repos/{owner}/{repo}/tags");
|
||||
Endpoints[101] = CreateEndpoint("/repos/{owner}/{repo}/teams");
|
||||
Endpoints[102] = CreateEndpoint("/repos/{owner}/{repo}/watchers");
|
||||
Endpoints[103] = CreateEndpoint("/repos/{owner}/{repo}/git/blobs");
|
||||
Endpoints[104] = CreateEndpoint("/repos/{owner}/{repo}/git/commits");
|
||||
Endpoints[105] = CreateEndpoint("/repos/{owner}/{repo}/git/refs");
|
||||
Endpoints[106] = CreateEndpoint("/repos/{owner}/{repo}/git/tags");
|
||||
Endpoints[107] = CreateEndpoint("/repos/{owner}/{repo}/git/trees");
|
||||
Endpoints[108] = CreateEndpoint("/repos/{owner}/{repo}/issues/comments");
|
||||
Endpoints[109] = CreateEndpoint("/repos/{owner}/{repo}/issues/events");
|
||||
Endpoints[110] = CreateEndpoint("/repos/{owner}/{repo}/pulls/comments");
|
||||
Endpoints[111] = CreateEndpoint("/repos/{owner}/{repo}/stats/code_frequency");
|
||||
Endpoints[112] = CreateEndpoint("/repos/{owner}/{repo}/stats/commit_activity");
|
||||
Endpoints[113] = CreateEndpoint("/repos/{owner}/{repo}/stats/contributors");
|
||||
Endpoints[114] = CreateEndpoint("/repos/{owner}/{repo}/stats/participation");
|
||||
Endpoints[115] = CreateEndpoint("/repos/{owner}/{repo}/stats/punch_card");
|
||||
Endpoints[116] = CreateEndpoint("/repos/{owner}/{repo}/git/blobs/{shaCode}");
|
||||
Endpoints[117] = CreateEndpoint("/repos/{owner}/{repo}/git/commits/{shaCode}");
|
||||
Endpoints[118] = CreateEndpoint("/repos/{owner}/{repo}/git/refs/{ref}");
|
||||
Endpoints[119] = CreateEndpoint("/repos/{owner}/{repo}/git/tags/{shaCode}");
|
||||
Endpoints[120] = CreateEndpoint("/repos/{owner}/{repo}/git/trees/{shaCode}");
|
||||
Endpoints[121] = CreateEndpoint("/repos/{owner}/{repo}/issues/comments/{commentId}");
|
||||
Endpoints[122] = CreateEndpoint("/repos/{owner}/{repo}/issues/events/{eventId}");
|
||||
Endpoints[123] = CreateEndpoint("/repos/{owner}/{repo}/pulls/comments/{commentId}");
|
||||
Endpoints[124] = CreateEndpoint("/repos/{owner}/{repo}/releases/assets/{id}");
|
||||
Endpoints[125] = CreateEndpoint("/repos/{owner}/{repo}/assignees/{assignee}");
|
||||
Endpoints[126] = CreateEndpoint("/repos/{owner}/{repo}/branches/{branch}");
|
||||
Endpoints[127] = CreateEndpoint("/repos/{owner}/{repo}/collaborators/{user}");
|
||||
Endpoints[128] = CreateEndpoint("/repos/{owner}/{repo}/comments/{commentId}");
|
||||
Endpoints[129] = CreateEndpoint("/repos/{owner}/{repo}/commits/{shaCode}");
|
||||
Endpoints[130] = CreateEndpoint("/repos/{owner}/{repo}/contents/{path}");
|
||||
Endpoints[131] = CreateEndpoint("/repos/{owner}/{repo}/downloads/{downloadId}");
|
||||
Endpoints[132] = CreateEndpoint("/repos/{owner}/{repo}/hooks/{hookId}");
|
||||
Endpoints[133] = CreateEndpoint("/repos/{owner}/{repo}/issues/{number}");
|
||||
Endpoints[134] = CreateEndpoint("/repos/{owner}/{repo}/keys/{keyId}");
|
||||
Endpoints[135] = CreateEndpoint("/repos/{owner}/{repo}/labels/{name}");
|
||||
Endpoints[136] = CreateEndpoint("/repos/{owner}/{repo}/milestones/{number}");
|
||||
Endpoints[137] = CreateEndpoint("/repos/{owner}/{repo}/pulls/{number}");
|
||||
Endpoints[138] = CreateEndpoint("/repos/{owner}/{repo}/releases/{id}");
|
||||
Endpoints[139] = CreateEndpoint("/repos/{owner}/{repo}/statuses/{ref}");
|
||||
Endpoints[140] = CreateEndpoint("/repos/{owner}/{repo}/commits/{ref}/status");
|
||||
Endpoints[141] = CreateEndpoint("/repos/{owner}/{repo}/commits/{shaCode}/comments");
|
||||
Endpoints[142] = CreateEndpoint("/repos/{owner}/{repo}/deployments/{id}/statuses");
|
||||
Endpoints[143] = CreateEndpoint("/repos/{owner}/{repo}/hooks/{hookId}/tests");
|
||||
Endpoints[144] = CreateEndpoint("/repos/{owner}/{repo}/issues/{number}/comments");
|
||||
Endpoints[145] = CreateEndpoint("/repos/{owner}/{repo}/issues/{number}/events");
|
||||
Endpoints[146] = CreateEndpoint("/repos/{owner}/{repo}/issues/{number}/labels");
|
||||
Endpoints[147] = CreateEndpoint("/repos/{owner}/{repo}/milestones/{number}/labels");
|
||||
Endpoints[148] = CreateEndpoint("/repos/{owner}/{repo}/pulls/{number}/comments");
|
||||
Endpoints[149] = CreateEndpoint("/repos/{owner}/{repo}/pulls/{number}/commits");
|
||||
Endpoints[150] = CreateEndpoint("/repos/{owner}/{repo}/pulls/{number}/files");
|
||||
Endpoints[151] = CreateEndpoint("/repos/{owner}/{repo}/pulls/{number}/merge");
|
||||
Endpoints[152] = CreateEndpoint("/repos/{owner}/{repo}/releases/{id}/assets");
|
||||
Endpoints[153] = CreateEndpoint("/repos/{owner}/{repo}/issues/{number}/labels/{name}");
|
||||
Endpoints[154] = CreateEndpoint("/repos/{owner}/{repo}/{archive_format}/{path}");
|
||||
}
|
||||
|
||||
private void SetupRequests()
|
||||
{
|
||||
Requests = new HttpContext[155];
|
||||
Requests[0] = new DefaultHttpContext();
|
||||
Requests[0].RequestServices = CreateServices();
|
||||
Requests[0].Request.Method = "GET";
|
||||
Requests[0].Request.Path = "/emojis";
|
||||
Requests[1] = new DefaultHttpContext();
|
||||
Requests[1].RequestServices = CreateServices();
|
||||
Requests[1].Request.Method = "GET";
|
||||
Requests[1].Request.Path = "/events";
|
||||
Requests[2] = new DefaultHttpContext();
|
||||
Requests[2].RequestServices = CreateServices();
|
||||
Requests[2].Request.Method = "GET";
|
||||
Requests[2].Request.Path = "/feeds";
|
||||
Requests[3] = new DefaultHttpContext();
|
||||
Requests[3].RequestServices = CreateServices();
|
||||
Requests[3].Request.Method = "POST";
|
||||
Requests[3].Request.Path = "/gists";
|
||||
Requests[4] = new DefaultHttpContext();
|
||||
Requests[4].RequestServices = CreateServices();
|
||||
Requests[4].Request.Method = "GET";
|
||||
Requests[4].Request.Path = "/issues";
|
||||
Requests[5] = new DefaultHttpContext();
|
||||
Requests[5].RequestServices = CreateServices();
|
||||
Requests[5].Request.Method = "POST";
|
||||
Requests[5].Request.Path = "/markdown";
|
||||
Requests[6] = new DefaultHttpContext();
|
||||
Requests[6].RequestServices = CreateServices();
|
||||
Requests[6].Request.Method = "GET";
|
||||
Requests[6].Request.Path = "/meta";
|
||||
Requests[7] = new DefaultHttpContext();
|
||||
Requests[7].RequestServices = CreateServices();
|
||||
Requests[7].Request.Method = "PUT";
|
||||
Requests[7].Request.Path = "/notifications";
|
||||
Requests[8] = new DefaultHttpContext();
|
||||
Requests[8].RequestServices = CreateServices();
|
||||
Requests[8].Request.Method = "GET";
|
||||
Requests[8].Request.Path = "/rate_limit";
|
||||
Requests[9] = new DefaultHttpContext();
|
||||
Requests[9].RequestServices = CreateServices();
|
||||
Requests[9].Request.Method = "GET";
|
||||
Requests[9].Request.Path = "/repositories";
|
||||
Requests[10] = new DefaultHttpContext();
|
||||
Requests[10].RequestServices = CreateServices();
|
||||
Requests[10].Request.Method = "PATCH";
|
||||
Requests[10].Request.Path = "/user";
|
||||
Requests[11] = new DefaultHttpContext();
|
||||
Requests[11].RequestServices = CreateServices();
|
||||
Requests[11].Request.Method = "GET";
|
||||
Requests[11].Request.Path = "/users";
|
||||
Requests[12] = new DefaultHttpContext();
|
||||
Requests[12].RequestServices = CreateServices();
|
||||
Requests[12].Request.Method = "GET";
|
||||
Requests[12].Request.Path = "/gists/public";
|
||||
Requests[13] = new DefaultHttpContext();
|
||||
Requests[13].RequestServices = CreateServices();
|
||||
Requests[13].Request.Method = "GET";
|
||||
Requests[13].Request.Path = "/gists/starred";
|
||||
Requests[14] = new DefaultHttpContext();
|
||||
Requests[14].RequestServices = CreateServices();
|
||||
Requests[14].Request.Method = "GET";
|
||||
Requests[14].Request.Path = "/gitignore/templates";
|
||||
Requests[15] = new DefaultHttpContext();
|
||||
Requests[15].RequestServices = CreateServices();
|
||||
Requests[15].Request.Method = "POST";
|
||||
Requests[15].Request.Path = "/markdown/raw";
|
||||
Requests[16] = new DefaultHttpContext();
|
||||
Requests[16].RequestServices = CreateServices();
|
||||
Requests[16].Request.Method = "GET";
|
||||
Requests[16].Request.Path = "/search/code";
|
||||
Requests[17] = new DefaultHttpContext();
|
||||
Requests[17].RequestServices = CreateServices();
|
||||
Requests[17].Request.Method = "GET";
|
||||
Requests[17].Request.Path = "/search/issues";
|
||||
Requests[18] = new DefaultHttpContext();
|
||||
Requests[18].RequestServices = CreateServices();
|
||||
Requests[18].Request.Method = "GET";
|
||||
Requests[18].Request.Path = "/search/repositories";
|
||||
Requests[19] = new DefaultHttpContext();
|
||||
Requests[19].RequestServices = CreateServices();
|
||||
Requests[19].Request.Method = "GET";
|
||||
Requests[19].Request.Path = "/search/users";
|
||||
Requests[20] = new DefaultHttpContext();
|
||||
Requests[20].RequestServices = CreateServices();
|
||||
Requests[20].Request.Method = "POST";
|
||||
Requests[20].Request.Path = "/user/emails";
|
||||
Requests[21] = new DefaultHttpContext();
|
||||
Requests[21].RequestServices = CreateServices();
|
||||
Requests[21].Request.Method = "GET";
|
||||
Requests[21].Request.Path = "/user/followers";
|
||||
Requests[22] = new DefaultHttpContext();
|
||||
Requests[22].RequestServices = CreateServices();
|
||||
Requests[22].Request.Method = "GET";
|
||||
Requests[22].Request.Path = "/user/following";
|
||||
Requests[23] = new DefaultHttpContext();
|
||||
Requests[23].RequestServices = CreateServices();
|
||||
Requests[23].Request.Method = "GET";
|
||||
Requests[23].Request.Path = "/user/issues";
|
||||
Requests[24] = new DefaultHttpContext();
|
||||
Requests[24].RequestServices = CreateServices();
|
||||
Requests[24].Request.Method = "POST";
|
||||
Requests[24].Request.Path = "/user/keys";
|
||||
Requests[25] = new DefaultHttpContext();
|
||||
Requests[25].RequestServices = CreateServices();
|
||||
Requests[25].Request.Method = "GET";
|
||||
Requests[25].Request.Path = "/user/orgs";
|
||||
Requests[26] = new DefaultHttpContext();
|
||||
Requests[26].RequestServices = CreateServices();
|
||||
Requests[26].Request.Method = "POST";
|
||||
Requests[26].Request.Path = "/user/repos";
|
||||
Requests[27] = new DefaultHttpContext();
|
||||
Requests[27].RequestServices = CreateServices();
|
||||
Requests[27].Request.Method = "GET";
|
||||
Requests[27].Request.Path = "/user/starred";
|
||||
Requests[28] = new DefaultHttpContext();
|
||||
Requests[28].RequestServices = CreateServices();
|
||||
Requests[28].Request.Method = "GET";
|
||||
Requests[28].Request.Path = "/user/subscriptions";
|
||||
Requests[29] = new DefaultHttpContext();
|
||||
Requests[29].RequestServices = CreateServices();
|
||||
Requests[29].Request.Method = "GET";
|
||||
Requests[29].Request.Path = "/user/teams";
|
||||
Requests[30] = new DefaultHttpContext();
|
||||
Requests[30].RequestServices = CreateServices();
|
||||
Requests[30].Request.Method = "GET";
|
||||
Requests[30].Request.Path = "/legacy/repos/search/98f2805";
|
||||
Requests[31] = new DefaultHttpContext();
|
||||
Requests[31].RequestServices = CreateServices();
|
||||
Requests[31].Request.Method = "GET";
|
||||
Requests[31].Request.Path = "/legacy/user/email/d65b3";
|
||||
Requests[32] = new DefaultHttpContext();
|
||||
Requests[32].RequestServices = CreateServices();
|
||||
Requests[32].Request.Method = "GET";
|
||||
Requests[32].Request.Path = "/legacy/user/search/edc2298";
|
||||
Requests[33] = new DefaultHttpContext();
|
||||
Requests[33].RequestServices = CreateServices();
|
||||
Requests[33].Request.Method = "GET";
|
||||
Requests[33].Request.Path = "/legacy/issues/search/7f959/b12ea0da-b/49a3b/b371d06";
|
||||
Requests[34] = new DefaultHttpContext();
|
||||
Requests[34].RequestServices = CreateServices();
|
||||
Requests[34].Request.Method = "GET";
|
||||
Requests[34].Request.Path = "/gitignore/templates/0cb5dc32";
|
||||
Requests[35] = new DefaultHttpContext();
|
||||
Requests[35].RequestServices = CreateServices();
|
||||
Requests[35].Request.Method = "PATCH";
|
||||
Requests[35].Request.Path = "/notifications/threads/4bd8e";
|
||||
Requests[36] = new DefaultHttpContext();
|
||||
Requests[36].RequestServices = CreateServices();
|
||||
Requests[36].Request.Method = "PUT";
|
||||
Requests[36].Request.Path = "/user/following/e2c3a018";
|
||||
Requests[37] = new DefaultHttpContext();
|
||||
Requests[37].RequestServices = CreateServices();
|
||||
Requests[37].Request.Method = "GET";
|
||||
Requests[37].Request.Path = "/user/keys/7d82b";
|
||||
Requests[38] = new DefaultHttpContext();
|
||||
Requests[38].RequestServices = CreateServices();
|
||||
Requests[38].Request.Method = "PUT";
|
||||
Requests[38].Request.Path = "/notifications/threads/dd67d/subscription";
|
||||
Requests[39] = new DefaultHttpContext();
|
||||
Requests[39].RequestServices = CreateServices();
|
||||
Requests[39].Request.Method = "PUT";
|
||||
Requests[39].Request.Path = "/user/starred/0b99c/8783e";
|
||||
Requests[40] = new DefaultHttpContext();
|
||||
Requests[40].RequestServices = CreateServices();
|
||||
Requests[40].Request.Method = "PUT";
|
||||
Requests[40].Request.Path = "/user/subscriptions/384c7/2c13f";
|
||||
Requests[41] = new DefaultHttpContext();
|
||||
Requests[41].RequestServices = CreateServices();
|
||||
Requests[41].Request.Method = "PATCH";
|
||||
Requests[41].Request.Path = "/gists/e6d49";
|
||||
Requests[42] = new DefaultHttpContext();
|
||||
Requests[42].RequestServices = CreateServices();
|
||||
Requests[42].Request.Method = "PATCH";
|
||||
Requests[42].Request.Path = "/orgs/8ae9c";
|
||||
Requests[43] = new DefaultHttpContext();
|
||||
Requests[43].RequestServices = CreateServices();
|
||||
Requests[43].Request.Method = "PATCH";
|
||||
Requests[43].Request.Path = "/teams/4a7cc7";
|
||||
Requests[44] = new DefaultHttpContext();
|
||||
Requests[44].RequestServices = CreateServices();
|
||||
Requests[44].Request.Method = "GET";
|
||||
Requests[44].Request.Path = "/users/0a04d291";
|
||||
Requests[45] = new DefaultHttpContext();
|
||||
Requests[45].RequestServices = CreateServices();
|
||||
Requests[45].Request.Method = "POST";
|
||||
Requests[45].Request.Path = "/gists/08da6/comments";
|
||||
Requests[46] = new DefaultHttpContext();
|
||||
Requests[46].RequestServices = CreateServices();
|
||||
Requests[46].Request.Method = "POST";
|
||||
Requests[46].Request.Path = "/gists/fca54/forks";
|
||||
Requests[47] = new DefaultHttpContext();
|
||||
Requests[47].RequestServices = CreateServices();
|
||||
Requests[47].Request.Method = "PUT";
|
||||
Requests[47].Request.Path = "/gists/31f75/star";
|
||||
Requests[48] = new DefaultHttpContext();
|
||||
Requests[48].RequestServices = CreateServices();
|
||||
Requests[48].Request.Method = "GET";
|
||||
Requests[48].Request.Path = "/orgs/2b352/events";
|
||||
Requests[49] = new DefaultHttpContext();
|
||||
Requests[49].RequestServices = CreateServices();
|
||||
Requests[49].Request.Method = "GET";
|
||||
Requests[49].Request.Path = "/orgs/e08a9/issues";
|
||||
Requests[50] = new DefaultHttpContext();
|
||||
Requests[50].RequestServices = CreateServices();
|
||||
Requests[50].Request.Method = "GET";
|
||||
Requests[50].Request.Path = "/orgs/fddd5/members";
|
||||
Requests[51] = new DefaultHttpContext();
|
||||
Requests[51].RequestServices = CreateServices();
|
||||
Requests[51].Request.Method = "GET";
|
||||
Requests[51].Request.Path = "/orgs/a0018/public_members";
|
||||
Requests[52] = new DefaultHttpContext();
|
||||
Requests[52].RequestServices = CreateServices();
|
||||
Requests[52].Request.Method = "POST";
|
||||
Requests[52].Request.Path = "/orgs/459e6/repos";
|
||||
Requests[53] = new DefaultHttpContext();
|
||||
Requests[53].RequestServices = CreateServices();
|
||||
Requests[53].Request.Method = "POST";
|
||||
Requests[53].Request.Path = "/orgs/c50a3/teams";
|
||||
Requests[54] = new DefaultHttpContext();
|
||||
Requests[54].RequestServices = CreateServices();
|
||||
Requests[54].Request.Method = "GET";
|
||||
Requests[54].Request.Path = "/teams/6d7c70/members";
|
||||
Requests[55] = new DefaultHttpContext();
|
||||
Requests[55].RequestServices = CreateServices();
|
||||
Requests[55].Request.Method = "GET";
|
||||
Requests[55].Request.Path = "/teams/2c72a5/repos";
|
||||
Requests[56] = new DefaultHttpContext();
|
||||
Requests[56].RequestServices = CreateServices();
|
||||
Requests[56].Request.Method = "GET";
|
||||
Requests[56].Request.Path = "/users/0d7c82bc/events";
|
||||
Requests[57] = new DefaultHttpContext();
|
||||
Requests[57].RequestServices = CreateServices();
|
||||
Requests[57].Request.Method = "GET";
|
||||
Requests[57].Request.Path = "/users/dad59333/followers";
|
||||
Requests[58] = new DefaultHttpContext();
|
||||
Requests[58].RequestServices = CreateServices();
|
||||
Requests[58].Request.Method = "GET";
|
||||
Requests[58].Request.Path = "/users/d3cfc2f7/gists";
|
||||
Requests[59] = new DefaultHttpContext();
|
||||
Requests[59].RequestServices = CreateServices();
|
||||
Requests[59].Request.Method = "GET";
|
||||
Requests[59].Request.Path = "/users/74de59eb/keys";
|
||||
Requests[60] = new DefaultHttpContext();
|
||||
Requests[60].RequestServices = CreateServices();
|
||||
Requests[60].Request.Method = "GET";
|
||||
Requests[60].Request.Path = "/users/c8078ace/orgs";
|
||||
Requests[61] = new DefaultHttpContext();
|
||||
Requests[61].RequestServices = CreateServices();
|
||||
Requests[61].Request.Method = "GET";
|
||||
Requests[61].Request.Path = "/users/7bb096ec/received_events";
|
||||
Requests[62] = new DefaultHttpContext();
|
||||
Requests[62].RequestServices = CreateServices();
|
||||
Requests[62].Request.Method = "GET";
|
||||
Requests[62].Request.Path = "/users/8208dce8/repos";
|
||||
Requests[63] = new DefaultHttpContext();
|
||||
Requests[63].RequestServices = CreateServices();
|
||||
Requests[63].Request.Method = "GET";
|
||||
Requests[63].Request.Path = "/users/8da3e05c/starred";
|
||||
Requests[64] = new DefaultHttpContext();
|
||||
Requests[64].RequestServices = CreateServices();
|
||||
Requests[64].Request.Method = "GET";
|
||||
Requests[64].Request.Path = "/users/ddcd1749/subscriptions";
|
||||
Requests[65] = new DefaultHttpContext();
|
||||
Requests[65].RequestServices = CreateServices();
|
||||
Requests[65].Request.Method = "GET";
|
||||
Requests[65].Request.Path = "/users/528d35ef/received_events/public";
|
||||
Requests[66] = new DefaultHttpContext();
|
||||
Requests[66].RequestServices = CreateServices();
|
||||
Requests[66].Request.Method = "GET";
|
||||
Requests[66].Request.Path = "/users/9a36a9de/events/orgs/3864a";
|
||||
Requests[67] = new DefaultHttpContext();
|
||||
Requests[67].RequestServices = CreateServices();
|
||||
Requests[67].Request.Method = "PATCH";
|
||||
Requests[67].Request.Path = "/gists/29a38/comments/f955540b-";
|
||||
Requests[68] = new DefaultHttpContext();
|
||||
Requests[68].RequestServices = CreateServices();
|
||||
Requests[68].Request.Method = "GET";
|
||||
Requests[68].Request.Path = "/orgs/7b33c/members/fa7c6147";
|
||||
Requests[69] = new DefaultHttpContext();
|
||||
Requests[69].RequestServices = CreateServices();
|
||||
Requests[69].Request.Method = "PUT";
|
||||
Requests[69].Request.Path = "/orgs/97a4b/public_members/35fecf7f";
|
||||
Requests[70] = new DefaultHttpContext();
|
||||
Requests[70].RequestServices = CreateServices();
|
||||
Requests[70].Request.Method = "PUT";
|
||||
Requests[70].Request.Path = "/teams/969145/members/194d27ad";
|
||||
Requests[71] = new DefaultHttpContext();
|
||||
Requests[71].RequestServices = CreateServices();
|
||||
Requests[71].Request.Method = "PUT";
|
||||
Requests[71].Request.Path = "/teams/90a622/memberships/88477f8b";
|
||||
Requests[72] = new DefaultHttpContext();
|
||||
Requests[72].RequestServices = CreateServices();
|
||||
Requests[72].Request.Method = "GET";
|
||||
Requests[72].Request.Path = "/users/efc0aad4/following/bc58bd8c-7";
|
||||
Requests[73] = new DefaultHttpContext();
|
||||
Requests[73].RequestServices = CreateServices();
|
||||
Requests[73].Request.Method = "GET";
|
||||
Requests[73].Request.Path = "/teams/98d389/repos/74b04/05c77";
|
||||
Requests[74] = new DefaultHttpContext();
|
||||
Requests[74].RequestServices = CreateServices();
|
||||
Requests[74].Request.Method = "PATCH";
|
||||
Requests[74].Request.Path = "/repos/fbc82/446db";
|
||||
Requests[75] = new DefaultHttpContext();
|
||||
Requests[75].RequestServices = CreateServices();
|
||||
Requests[75].Request.Method = "GET";
|
||||
Requests[75].Request.Path = "/networks/d914d/57c64/events";
|
||||
Requests[76] = new DefaultHttpContext();
|
||||
Requests[76].RequestServices = CreateServices();
|
||||
Requests[76].Request.Method = "GET";
|
||||
Requests[76].Request.Path = "/repos/67afd/b1bc5/assignees";
|
||||
Requests[77] = new DefaultHttpContext();
|
||||
Requests[77].RequestServices = CreateServices();
|
||||
Requests[77].Request.Method = "GET";
|
||||
Requests[77].Request.Path = "/repos/b2f87/ced1b/branches";
|
||||
Requests[78] = new DefaultHttpContext();
|
||||
Requests[78].RequestServices = CreateServices();
|
||||
Requests[78].Request.Method = "GET";
|
||||
Requests[78].Request.Path = "/repos/4c0cd/a3d94/collaborators";
|
||||
Requests[79] = new DefaultHttpContext();
|
||||
Requests[79].RequestServices = CreateServices();
|
||||
Requests[79].Request.Method = "GET";
|
||||
Requests[79].Request.Path = "/repos/1eab2/4cbac/comments";
|
||||
Requests[80] = new DefaultHttpContext();
|
||||
Requests[80].RequestServices = CreateServices();
|
||||
Requests[80].Request.Method = "GET";
|
||||
Requests[80].Request.Path = "/repos/5981b/de5a8/commits";
|
||||
Requests[81] = new DefaultHttpContext();
|
||||
Requests[81].RequestServices = CreateServices();
|
||||
Requests[81].Request.Method = "GET";
|
||||
Requests[81].Request.Path = "/repos/7ad40/db6ee/contributors";
|
||||
Requests[82] = new DefaultHttpContext();
|
||||
Requests[82].RequestServices = CreateServices();
|
||||
Requests[82].Request.Method = "POST";
|
||||
Requests[82].Request.Path = "/repos/8972a/86bb7/deployments";
|
||||
Requests[83] = new DefaultHttpContext();
|
||||
Requests[83].RequestServices = CreateServices();
|
||||
Requests[83].Request.Method = "GET";
|
||||
Requests[83].Request.Path = "/repos/c619b/d8f5a/downloads";
|
||||
Requests[84] = new DefaultHttpContext();
|
||||
Requests[84].RequestServices = CreateServices();
|
||||
Requests[84].Request.Method = "GET";
|
||||
Requests[84].Request.Path = "/repos/91509/bb53c/events";
|
||||
Requests[85] = new DefaultHttpContext();
|
||||
Requests[85].RequestServices = CreateServices();
|
||||
Requests[85].Request.Method = "POST";
|
||||
Requests[85].Request.Path = "/repos/9da59/f78cd/forks";
|
||||
Requests[86] = new DefaultHttpContext();
|
||||
Requests[86].RequestServices = CreateServices();
|
||||
Requests[86].Request.Method = "POST";
|
||||
Requests[86].Request.Path = "/repos/1484a/4e077/hooks";
|
||||
Requests[87] = new DefaultHttpContext();
|
||||
Requests[87].RequestServices = CreateServices();
|
||||
Requests[87].Request.Method = "POST";
|
||||
Requests[87].Request.Path = "/repos/c5793/4f77e/issues";
|
||||
Requests[88] = new DefaultHttpContext();
|
||||
Requests[88].RequestServices = CreateServices();
|
||||
Requests[88].Request.Method = "POST";
|
||||
Requests[88].Request.Path = "/repos/d4e39/2dd22/keys";
|
||||
Requests[89] = new DefaultHttpContext();
|
||||
Requests[89].RequestServices = CreateServices();
|
||||
Requests[89].Request.Method = "POST";
|
||||
Requests[89].Request.Path = "/repos/bd4f0/9cc66/labels";
|
||||
Requests[90] = new DefaultHttpContext();
|
||||
Requests[90].RequestServices = CreateServices();
|
||||
Requests[90].Request.Method = "GET";
|
||||
Requests[90].Request.Path = "/repos/6b934/aa4bd/languages";
|
||||
Requests[91] = new DefaultHttpContext();
|
||||
Requests[91].RequestServices = CreateServices();
|
||||
Requests[91].Request.Method = "POST";
|
||||
Requests[91].Request.Path = "/repos/8830a/88a98/merges";
|
||||
Requests[92] = new DefaultHttpContext();
|
||||
Requests[92].RequestServices = CreateServices();
|
||||
Requests[92].Request.Method = "POST";
|
||||
Requests[92].Request.Path = "/repos/9ce99/29222/milestones";
|
||||
Requests[93] = new DefaultHttpContext();
|
||||
Requests[93].RequestServices = CreateServices();
|
||||
Requests[93].Request.Method = "PUT";
|
||||
Requests[93].Request.Path = "/repos/a106c/ac6a4/notifications";
|
||||
Requests[94] = new DefaultHttpContext();
|
||||
Requests[94].RequestServices = CreateServices();
|
||||
Requests[94].Request.Method = "POST";
|
||||
Requests[94].Request.Path = "/repos/0e52f/ca9e5/pulls";
|
||||
Requests[95] = new DefaultHttpContext();
|
||||
Requests[95].RequestServices = CreateServices();
|
||||
Requests[95].Request.Method = "GET";
|
||||
Requests[95].Request.Path = "/repos/37e7a/7aa03/readme";
|
||||
Requests[96] = new DefaultHttpContext();
|
||||
Requests[96].RequestServices = CreateServices();
|
||||
Requests[96].Request.Method = "POST";
|
||||
Requests[96].Request.Path = "/repos/cf543/a26e5/releases";
|
||||
Requests[97] = new DefaultHttpContext();
|
||||
Requests[97].RequestServices = CreateServices();
|
||||
Requests[97].Request.Method = "GET";
|
||||
Requests[97].Request.Path = "/repos/26330/2998f/stargazers";
|
||||
Requests[98] = new DefaultHttpContext();
|
||||
Requests[98].RequestServices = CreateServices();
|
||||
Requests[98].Request.Method = "GET";
|
||||
Requests[98].Request.Path = "/repos/4192a/8d012/subscribers";
|
||||
Requests[99] = new DefaultHttpContext();
|
||||
Requests[99].RequestServices = CreateServices();
|
||||
Requests[99].Request.Method = "PUT";
|
||||
Requests[99].Request.Path = "/repos/7bf2f/ec3e8/subscription";
|
||||
Requests[100] = new DefaultHttpContext();
|
||||
Requests[100].RequestServices = CreateServices();
|
||||
Requests[100].Request.Method = "GET";
|
||||
Requests[100].Request.Path = "/repos/9285d/2386a/tags";
|
||||
Requests[101] = new DefaultHttpContext();
|
||||
Requests[101].RequestServices = CreateServices();
|
||||
Requests[101].Request.Method = "GET";
|
||||
Requests[101].Request.Path = "/repos/ba9c2/c995c/teams";
|
||||
Requests[102] = new DefaultHttpContext();
|
||||
Requests[102].RequestServices = CreateServices();
|
||||
Requests[102].Request.Method = "GET";
|
||||
Requests[102].Request.Path = "/repos/15c8d/35395/watchers";
|
||||
Requests[103] = new DefaultHttpContext();
|
||||
Requests[103].RequestServices = CreateServices();
|
||||
Requests[103].Request.Method = "POST";
|
||||
Requests[103].Request.Path = "/repos/3e849/531ef/git/blobs";
|
||||
Requests[104] = new DefaultHttpContext();
|
||||
Requests[104].RequestServices = CreateServices();
|
||||
Requests[104].Request.Method = "POST";
|
||||
Requests[104].Request.Path = "/repos/3bcbc/5d8bc/git/commits";
|
||||
Requests[105] = new DefaultHttpContext();
|
||||
Requests[105].RequestServices = CreateServices();
|
||||
Requests[105].Request.Method = "POST";
|
||||
Requests[105].Request.Path = "/repos/65917/4297b/git/refs";
|
||||
Requests[106] = new DefaultHttpContext();
|
||||
Requests[106].RequestServices = CreateServices();
|
||||
Requests[106].Request.Method = "POST";
|
||||
Requests[106].Request.Path = "/repos/5aadb/450d4/git/tags";
|
||||
Requests[107] = new DefaultHttpContext();
|
||||
Requests[107].RequestServices = CreateServices();
|
||||
Requests[107].Request.Method = "POST";
|
||||
Requests[107].Request.Path = "/repos/4c306/f056f/git/trees";
|
||||
Requests[108] = new DefaultHttpContext();
|
||||
Requests[108].RequestServices = CreateServices();
|
||||
Requests[108].Request.Method = "GET";
|
||||
Requests[108].Request.Path = "/repos/9da82/d041c/issues/comments";
|
||||
Requests[109] = new DefaultHttpContext();
|
||||
Requests[109].RequestServices = CreateServices();
|
||||
Requests[109].Request.Method = "GET";
|
||||
Requests[109].Request.Path = "/repos/06bb5/1352f/issues/events";
|
||||
Requests[110] = new DefaultHttpContext();
|
||||
Requests[110].RequestServices = CreateServices();
|
||||
Requests[110].Request.Method = "GET";
|
||||
Requests[110].Request.Path = "/repos/f87fb/e0543/pulls/comments";
|
||||
Requests[111] = new DefaultHttpContext();
|
||||
Requests[111].RequestServices = CreateServices();
|
||||
Requests[111].Request.Method = "GET";
|
||||
Requests[111].Request.Path = "/repos/b6d34/d0b39/stats/code_frequency";
|
||||
Requests[112] = new DefaultHttpContext();
|
||||
Requests[112].RequestServices = CreateServices();
|
||||
Requests[112].Request.Method = "GET";
|
||||
Requests[112].Request.Path = "/repos/e8d05/4707e/stats/commit_activity";
|
||||
Requests[113] = new DefaultHttpContext();
|
||||
Requests[113].RequestServices = CreateServices();
|
||||
Requests[113].Request.Method = "GET";
|
||||
Requests[113].Request.Path = "/repos/48d7e/0ecd3/stats/contributors";
|
||||
Requests[114] = new DefaultHttpContext();
|
||||
Requests[114].RequestServices = CreateServices();
|
||||
Requests[114].Request.Method = "GET";
|
||||
Requests[114].Request.Path = "/repos/8964b/6e8f5/stats/participation";
|
||||
Requests[115] = new DefaultHttpContext();
|
||||
Requests[115].RequestServices = CreateServices();
|
||||
Requests[115].Request.Method = "GET";
|
||||
Requests[115].Request.Path = "/repos/37374/f039d/stats/punch_card";
|
||||
Requests[116] = new DefaultHttpContext();
|
||||
Requests[116].RequestServices = CreateServices();
|
||||
Requests[116].Request.Method = "GET";
|
||||
Requests[116].Request.Path = "/repos/14566/a474b/git/blobs/04b85a8";
|
||||
Requests[117] = new DefaultHttpContext();
|
||||
Requests[117].RequestServices = CreateServices();
|
||||
Requests[117].Request.Method = "GET";
|
||||
Requests[117].Request.Path = "/repos/31a30/3ea34/git/commits/27948b9";
|
||||
Requests[118] = new DefaultHttpContext();
|
||||
Requests[118].RequestServices = CreateServices();
|
||||
Requests[118].Request.Method = "PATCH";
|
||||
Requests[118].Request.Path = "/repos/2c8ad/e2765/git/refs/67cc5";
|
||||
Requests[119] = new DefaultHttpContext();
|
||||
Requests[119].RequestServices = CreateServices();
|
||||
Requests[119].Request.Method = "GET";
|
||||
Requests[119].Request.Path = "/repos/739be/3acb7/git/tags/6c6430c";
|
||||
Requests[120] = new DefaultHttpContext();
|
||||
Requests[120].RequestServices = CreateServices();
|
||||
Requests[120].Request.Method = "GET";
|
||||
Requests[120].Request.Path = "/repos/5a112/21ae4/git/trees/fe88304";
|
||||
Requests[121] = new DefaultHttpContext();
|
||||
Requests[121].RequestServices = CreateServices();
|
||||
Requests[121].Request.Method = "PATCH";
|
||||
Requests[121].Request.Path = "/repos/76ed1/51c63/issues/comments/c9208b29-";
|
||||
Requests[122] = new DefaultHttpContext();
|
||||
Requests[122].RequestServices = CreateServices();
|
||||
Requests[122].Request.Method = "GET";
|
||||
Requests[122].Request.Path = "/repos/8230d/17f20/issues/events/5e4ea0f";
|
||||
Requests[123] = new DefaultHttpContext();
|
||||
Requests[123].RequestServices = CreateServices();
|
||||
Requests[123].Request.Method = "PATCH";
|
||||
Requests[123].Request.Path = "/repos/fa5f3/b4ecf/pulls/comments/1e93db69-";
|
||||
Requests[124] = new DefaultHttpContext();
|
||||
Requests[124].RequestServices = CreateServices();
|
||||
Requests[124].Request.Method = "PATCH";
|
||||
Requests[124].Request.Path = "/repos/f3b86/5793e/releases/assets/b21e5";
|
||||
Requests[125] = new DefaultHttpContext();
|
||||
Requests[125].RequestServices = CreateServices();
|
||||
Requests[125].Request.Method = "GET";
|
||||
Requests[125].Request.Path = "/repos/0df2f/f1d8e/assignees/87a41d15";
|
||||
Requests[126] = new DefaultHttpContext();
|
||||
Requests[126].RequestServices = CreateServices();
|
||||
Requests[126].Request.Method = "GET";
|
||||
Requests[126].Request.Path = "/repos/f0062/df752/branches/d18f91";
|
||||
Requests[127] = new DefaultHttpContext();
|
||||
Requests[127].RequestServices = CreateServices();
|
||||
Requests[127].Request.Method = "PUT";
|
||||
Requests[127].Request.Path = "/repos/022eb/1696a/collaborators/59494";
|
||||
Requests[128] = new DefaultHttpContext();
|
||||
Requests[128].RequestServices = CreateServices();
|
||||
Requests[128].Request.Method = "PATCH";
|
||||
Requests[128].Request.Path = "/repos/0f74c/4f864/comments/5a8b1f18-";
|
||||
Requests[129] = new DefaultHttpContext();
|
||||
Requests[129].RequestServices = CreateServices();
|
||||
Requests[129].Request.Method = "GET";
|
||||
Requests[129].Request.Path = "/repos/08262/d4859/commits/0459132";
|
||||
Requests[130] = new DefaultHttpContext();
|
||||
Requests[130].RequestServices = CreateServices();
|
||||
Requests[130].Request.Method = "PUT";
|
||||
Requests[130].Request.Path = "/repos/9e587/5da72/contents/3b37c";
|
||||
Requests[131] = new DefaultHttpContext();
|
||||
Requests[131].RequestServices = CreateServices();
|
||||
Requests[131].Request.Method = "GET";
|
||||
Requests[131].Request.Path = "/repos/aeabf/fb931/downloads/928b7eef-a";
|
||||
Requests[132] = new DefaultHttpContext();
|
||||
Requests[132].RequestServices = CreateServices();
|
||||
Requests[132].Request.Method = "PATCH";
|
||||
Requests[132].Request.Path = "/repos/cb76c/71512/hooks/e0a971";
|
||||
Requests[133] = new DefaultHttpContext();
|
||||
Requests[133].RequestServices = CreateServices();
|
||||
Requests[133].Request.Method = "PATCH";
|
||||
Requests[133].Request.Path = "/repos/a44e1/81a70/issues/fedabf";
|
||||
Requests[134] = new DefaultHttpContext();
|
||||
Requests[134].RequestServices = CreateServices();
|
||||
Requests[134].Request.Method = "GET";
|
||||
Requests[134].Request.Path = "/repos/d776f/19a02/keys/9e5b3";
|
||||
Requests[135] = new DefaultHttpContext();
|
||||
Requests[135].RequestServices = CreateServices();
|
||||
Requests[135].Request.Method = "PATCH";
|
||||
Requests[135].Request.Path = "/repos/b8532/04123/labels/d3c1d";
|
||||
Requests[136] = new DefaultHttpContext();
|
||||
Requests[136].RequestServices = CreateServices();
|
||||
Requests[136].Request.Method = "PATCH";
|
||||
Requests[136].Request.Path = "/repos/1d10a/9efd4/milestones/f673c2";
|
||||
Requests[137] = new DefaultHttpContext();
|
||||
Requests[137].RequestServices = CreateServices();
|
||||
Requests[137].Request.Method = "PATCH";
|
||||
Requests[137].Request.Path = "/repos/3aa16/84330/pulls/6dcd1f";
|
||||
Requests[138] = new DefaultHttpContext();
|
||||
Requests[138].RequestServices = CreateServices();
|
||||
Requests[138].Request.Method = "PATCH";
|
||||
Requests[138].Request.Path = "/repos/eb98f/fd492/releases/a070f";
|
||||
Requests[139] = new DefaultHttpContext();
|
||||
Requests[139].RequestServices = CreateServices();
|
||||
Requests[139].Request.Method = "POST";
|
||||
Requests[139].Request.Path = "/repos/f1040/ca625/statuses/a1554";
|
||||
Requests[140] = new DefaultHttpContext();
|
||||
Requests[140].RequestServices = CreateServices();
|
||||
Requests[140].Request.Method = "GET";
|
||||
Requests[140].Request.Path = "/repos/5e573/09410/commits/740ca/status";
|
||||
Requests[141] = new DefaultHttpContext();
|
||||
Requests[141].RequestServices = CreateServices();
|
||||
Requests[141].Request.Method = "POST";
|
||||
Requests[141].Request.Path = "/repos/25dd0/256a3/commits/088d12d/comments";
|
||||
Requests[142] = new DefaultHttpContext();
|
||||
Requests[142].RequestServices = CreateServices();
|
||||
Requests[142].Request.Method = "POST";
|
||||
Requests[142].Request.Path = "/repos/50b76/80795/deployments/faedd/statuses";
|
||||
Requests[143] = new DefaultHttpContext();
|
||||
Requests[143].RequestServices = CreateServices();
|
||||
Requests[143].Request.Method = "POST";
|
||||
Requests[143].Request.Path = "/repos/0c54e/6485c/hooks/82463a/tests";
|
||||
Requests[144] = new DefaultHttpContext();
|
||||
Requests[144].RequestServices = CreateServices();
|
||||
Requests[144].Request.Method = "POST";
|
||||
Requests[144].Request.Path = "/repos/07cf6/23b13/issues/f0dd8f/comments";
|
||||
Requests[145] = new DefaultHttpContext();
|
||||
Requests[145].RequestServices = CreateServices();
|
||||
Requests[145].Request.Method = "GET";
|
||||
Requests[145].Request.Path = "/repos/23f9b/f2fd8/issues/3fe64f/events";
|
||||
Requests[146] = new DefaultHttpContext();
|
||||
Requests[146].RequestServices = CreateServices();
|
||||
Requests[146].Request.Method = "PUT";
|
||||
Requests[146].Request.Path = "/repos/5b3d7/ca96e/issues/936334/labels";
|
||||
Requests[147] = new DefaultHttpContext();
|
||||
Requests[147].RequestServices = CreateServices();
|
||||
Requests[147].Request.Method = "GET";
|
||||
Requests[147].Request.Path = "/repos/cd644/3304a/milestones/166fae/labels";
|
||||
Requests[148] = new DefaultHttpContext();
|
||||
Requests[148].RequestServices = CreateServices();
|
||||
Requests[148].Request.Method = "POST";
|
||||
Requests[148].Request.Path = "/repos/33da8/9f808/pulls/f1e922/comments";
|
||||
Requests[149] = new DefaultHttpContext();
|
||||
Requests[149].RequestServices = CreateServices();
|
||||
Requests[149].Request.Method = "GET";
|
||||
Requests[149].Request.Path = "/repos/be208/fc905/pulls/7e240f/commits";
|
||||
Requests[150] = new DefaultHttpContext();
|
||||
Requests[150].RequestServices = CreateServices();
|
||||
Requests[150].Request.Method = "GET";
|
||||
Requests[150].Request.Path = "/repos/3c706/a56bc/pulls/651d9a/files";
|
||||
Requests[151] = new DefaultHttpContext();
|
||||
Requests[151].RequestServices = CreateServices();
|
||||
Requests[151].Request.Method = "PUT";
|
||||
Requests[151].Request.Path = "/repos/ea5a0/36e73/pulls/760f68/merge";
|
||||
Requests[152] = new DefaultHttpContext();
|
||||
Requests[152].RequestServices = CreateServices();
|
||||
Requests[152].Request.Method = "GET";
|
||||
Requests[152].Request.Path = "/repos/9362e/2a504/releases/4105d/assets";
|
||||
Requests[153] = new DefaultHttpContext();
|
||||
Requests[153].RequestServices = CreateServices();
|
||||
Requests[153].Request.Method = "DELETE";
|
||||
Requests[153].Request.Path = "/repos/39dc3/47180/issues/5b5277/labels/fc82a";
|
||||
Requests[154] = new DefaultHttpContext();
|
||||
Requests[154].RequestServices = CreateServices();
|
||||
Requests[154].Request.Method = "GET";
|
||||
Requests[154].Request.Path = "/repos/91437/d62a4/5582f507-3991-/3e89b";
|
||||
}
|
||||
|
||||
private Matcher SetupMatcher(MatcherBuilder builder)
|
||||
{
|
||||
builder.AddEndpoint(Endpoints[0]);
|
||||
builder.AddEndpoint(Endpoints[1]);
|
||||
builder.AddEndpoint(Endpoints[2]);
|
||||
builder.AddEndpoint(Endpoints[3]);
|
||||
builder.AddEndpoint(Endpoints[4]);
|
||||
builder.AddEndpoint(Endpoints[5]);
|
||||
builder.AddEndpoint(Endpoints[6]);
|
||||
builder.AddEndpoint(Endpoints[7]);
|
||||
builder.AddEndpoint(Endpoints[8]);
|
||||
builder.AddEndpoint(Endpoints[9]);
|
||||
builder.AddEndpoint(Endpoints[10]);
|
||||
builder.AddEndpoint(Endpoints[11]);
|
||||
builder.AddEndpoint(Endpoints[12]);
|
||||
builder.AddEndpoint(Endpoints[13]);
|
||||
builder.AddEndpoint(Endpoints[14]);
|
||||
builder.AddEndpoint(Endpoints[15]);
|
||||
builder.AddEndpoint(Endpoints[16]);
|
||||
builder.AddEndpoint(Endpoints[17]);
|
||||
builder.AddEndpoint(Endpoints[18]);
|
||||
builder.AddEndpoint(Endpoints[19]);
|
||||
builder.AddEndpoint(Endpoints[20]);
|
||||
builder.AddEndpoint(Endpoints[21]);
|
||||
builder.AddEndpoint(Endpoints[22]);
|
||||
builder.AddEndpoint(Endpoints[23]);
|
||||
builder.AddEndpoint(Endpoints[24]);
|
||||
builder.AddEndpoint(Endpoints[25]);
|
||||
builder.AddEndpoint(Endpoints[26]);
|
||||
builder.AddEndpoint(Endpoints[27]);
|
||||
builder.AddEndpoint(Endpoints[28]);
|
||||
builder.AddEndpoint(Endpoints[29]);
|
||||
builder.AddEndpoint(Endpoints[30]);
|
||||
builder.AddEndpoint(Endpoints[31]);
|
||||
builder.AddEndpoint(Endpoints[32]);
|
||||
builder.AddEndpoint(Endpoints[33]);
|
||||
builder.AddEndpoint(Endpoints[34]);
|
||||
builder.AddEndpoint(Endpoints[35]);
|
||||
builder.AddEndpoint(Endpoints[36]);
|
||||
builder.AddEndpoint(Endpoints[37]);
|
||||
builder.AddEndpoint(Endpoints[38]);
|
||||
builder.AddEndpoint(Endpoints[39]);
|
||||
builder.AddEndpoint(Endpoints[40]);
|
||||
builder.AddEndpoint(Endpoints[41]);
|
||||
builder.AddEndpoint(Endpoints[42]);
|
||||
builder.AddEndpoint(Endpoints[43]);
|
||||
builder.AddEndpoint(Endpoints[44]);
|
||||
builder.AddEndpoint(Endpoints[45]);
|
||||
builder.AddEndpoint(Endpoints[46]);
|
||||
builder.AddEndpoint(Endpoints[47]);
|
||||
builder.AddEndpoint(Endpoints[48]);
|
||||
builder.AddEndpoint(Endpoints[49]);
|
||||
builder.AddEndpoint(Endpoints[50]);
|
||||
builder.AddEndpoint(Endpoints[51]);
|
||||
builder.AddEndpoint(Endpoints[52]);
|
||||
builder.AddEndpoint(Endpoints[53]);
|
||||
builder.AddEndpoint(Endpoints[54]);
|
||||
builder.AddEndpoint(Endpoints[55]);
|
||||
builder.AddEndpoint(Endpoints[56]);
|
||||
builder.AddEndpoint(Endpoints[57]);
|
||||
builder.AddEndpoint(Endpoints[58]);
|
||||
builder.AddEndpoint(Endpoints[59]);
|
||||
builder.AddEndpoint(Endpoints[60]);
|
||||
builder.AddEndpoint(Endpoints[61]);
|
||||
builder.AddEndpoint(Endpoints[62]);
|
||||
builder.AddEndpoint(Endpoints[63]);
|
||||
builder.AddEndpoint(Endpoints[64]);
|
||||
builder.AddEndpoint(Endpoints[65]);
|
||||
builder.AddEndpoint(Endpoints[66]);
|
||||
builder.AddEndpoint(Endpoints[67]);
|
||||
builder.AddEndpoint(Endpoints[68]);
|
||||
builder.AddEndpoint(Endpoints[69]);
|
||||
builder.AddEndpoint(Endpoints[70]);
|
||||
builder.AddEndpoint(Endpoints[71]);
|
||||
builder.AddEndpoint(Endpoints[72]);
|
||||
builder.AddEndpoint(Endpoints[73]);
|
||||
builder.AddEndpoint(Endpoints[74]);
|
||||
builder.AddEndpoint(Endpoints[75]);
|
||||
builder.AddEndpoint(Endpoints[76]);
|
||||
builder.AddEndpoint(Endpoints[77]);
|
||||
builder.AddEndpoint(Endpoints[78]);
|
||||
builder.AddEndpoint(Endpoints[79]);
|
||||
builder.AddEndpoint(Endpoints[80]);
|
||||
builder.AddEndpoint(Endpoints[81]);
|
||||
builder.AddEndpoint(Endpoints[82]);
|
||||
builder.AddEndpoint(Endpoints[83]);
|
||||
builder.AddEndpoint(Endpoints[84]);
|
||||
builder.AddEndpoint(Endpoints[85]);
|
||||
builder.AddEndpoint(Endpoints[86]);
|
||||
builder.AddEndpoint(Endpoints[87]);
|
||||
builder.AddEndpoint(Endpoints[88]);
|
||||
builder.AddEndpoint(Endpoints[89]);
|
||||
builder.AddEndpoint(Endpoints[90]);
|
||||
builder.AddEndpoint(Endpoints[91]);
|
||||
builder.AddEndpoint(Endpoints[92]);
|
||||
builder.AddEndpoint(Endpoints[93]);
|
||||
builder.AddEndpoint(Endpoints[94]);
|
||||
builder.AddEndpoint(Endpoints[95]);
|
||||
builder.AddEndpoint(Endpoints[96]);
|
||||
builder.AddEndpoint(Endpoints[97]);
|
||||
builder.AddEndpoint(Endpoints[98]);
|
||||
builder.AddEndpoint(Endpoints[99]);
|
||||
builder.AddEndpoint(Endpoints[100]);
|
||||
builder.AddEndpoint(Endpoints[101]);
|
||||
builder.AddEndpoint(Endpoints[102]);
|
||||
builder.AddEndpoint(Endpoints[103]);
|
||||
builder.AddEndpoint(Endpoints[104]);
|
||||
builder.AddEndpoint(Endpoints[105]);
|
||||
builder.AddEndpoint(Endpoints[106]);
|
||||
builder.AddEndpoint(Endpoints[107]);
|
||||
builder.AddEndpoint(Endpoints[108]);
|
||||
builder.AddEndpoint(Endpoints[109]);
|
||||
builder.AddEndpoint(Endpoints[110]);
|
||||
builder.AddEndpoint(Endpoints[111]);
|
||||
builder.AddEndpoint(Endpoints[112]);
|
||||
builder.AddEndpoint(Endpoints[113]);
|
||||
builder.AddEndpoint(Endpoints[114]);
|
||||
builder.AddEndpoint(Endpoints[115]);
|
||||
builder.AddEndpoint(Endpoints[116]);
|
||||
builder.AddEndpoint(Endpoints[117]);
|
||||
builder.AddEndpoint(Endpoints[118]);
|
||||
builder.AddEndpoint(Endpoints[119]);
|
||||
builder.AddEndpoint(Endpoints[120]);
|
||||
builder.AddEndpoint(Endpoints[121]);
|
||||
builder.AddEndpoint(Endpoints[122]);
|
||||
builder.AddEndpoint(Endpoints[123]);
|
||||
builder.AddEndpoint(Endpoints[124]);
|
||||
builder.AddEndpoint(Endpoints[125]);
|
||||
builder.AddEndpoint(Endpoints[126]);
|
||||
builder.AddEndpoint(Endpoints[127]);
|
||||
builder.AddEndpoint(Endpoints[128]);
|
||||
builder.AddEndpoint(Endpoints[129]);
|
||||
builder.AddEndpoint(Endpoints[130]);
|
||||
builder.AddEndpoint(Endpoints[131]);
|
||||
builder.AddEndpoint(Endpoints[132]);
|
||||
builder.AddEndpoint(Endpoints[133]);
|
||||
builder.AddEndpoint(Endpoints[134]);
|
||||
builder.AddEndpoint(Endpoints[135]);
|
||||
builder.AddEndpoint(Endpoints[136]);
|
||||
builder.AddEndpoint(Endpoints[137]);
|
||||
builder.AddEndpoint(Endpoints[138]);
|
||||
builder.AddEndpoint(Endpoints[139]);
|
||||
builder.AddEndpoint(Endpoints[140]);
|
||||
builder.AddEndpoint(Endpoints[141]);
|
||||
builder.AddEndpoint(Endpoints[142]);
|
||||
builder.AddEndpoint(Endpoints[143]);
|
||||
builder.AddEndpoint(Endpoints[144]);
|
||||
builder.AddEndpoint(Endpoints[145]);
|
||||
builder.AddEndpoint(Endpoints[146]);
|
||||
builder.AddEndpoint(Endpoints[147]);
|
||||
builder.AddEndpoint(Endpoints[148]);
|
||||
builder.AddEndpoint(Endpoints[149]);
|
||||
builder.AddEndpoint(Endpoints[150]);
|
||||
builder.AddEndpoint(Endpoints[151]);
|
||||
builder.AddEndpoint(Endpoints[152]);
|
||||
builder.AddEndpoint(Endpoints[153]);
|
||||
builder.AddEndpoint(Endpoints[154]);
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
// 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 BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Matching
|
||||
{
|
||||
public class MatcherFindCandidateSetSingleEntryBenchmark : EndpointRoutingBenchmarkBase
|
||||
{
|
||||
// SegmentCount should be max-segments + 1
|
||||
private const int SegmentCount = 2;
|
||||
|
||||
private TrivialMatcher _baseline;
|
||||
private DfaMatcher _dfa;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
Endpoints = new RouteEndpoint[1];
|
||||
Endpoints[0] = CreateEndpoint("/plaintext");
|
||||
|
||||
Requests = new HttpContext[1];
|
||||
Requests[0] = new DefaultHttpContext();
|
||||
Requests[0].RequestServices = CreateServices();
|
||||
Requests[0].Request.Path = "/plaintext";
|
||||
|
||||
_baseline = (TrivialMatcher)SetupMatcher(new TrivialMatcherBuilder());
|
||||
_dfa = (DfaMatcher)SetupMatcher(CreateDfaMatcherBuilder());
|
||||
}
|
||||
|
||||
private Matcher SetupMatcher(MatcherBuilder builder)
|
||||
{
|
||||
builder.AddEndpoint(Endpoints[0]);
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void Baseline()
|
||||
{
|
||||
var httpContext = Requests[0];
|
||||
var path = httpContext.Request.Path.Value;
|
||||
var segments = new ReadOnlySpan<PathSegment>(Array.Empty<PathSegment>());
|
||||
|
||||
var candidates = _baseline.FindCandidateSet(path, segments);
|
||||
|
||||
var endpoint = candidates[0].Endpoint;
|
||||
Validate(Requests[0], Endpoints[0], endpoint);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void Dfa()
|
||||
{
|
||||
var httpContext = Requests[0];
|
||||
var path = httpContext.Request.Path.Value;
|
||||
Span<PathSegment> segments = stackalloc PathSegment[SegmentCount];
|
||||
var count = FastPathTokenizer.Tokenize(path, segments);
|
||||
|
||||
var candidates = _dfa.FindCandidateSet(httpContext, path, segments.Slice(0, count));
|
||||
|
||||
var endpoint = candidates[0].Endpoint;
|
||||
Validate(Requests[0], Endpoints[0], endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
// 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 BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Matching
|
||||
{
|
||||
public class MatcherFindCandidateSetSmallEntryCountBenchmark : EndpointRoutingBenchmarkBase
|
||||
{
|
||||
// SegmentCount should be max-segments + 1
|
||||
private const int SegmentCount = 6;
|
||||
|
||||
private TrivialMatcher _baseline;
|
||||
private DfaMatcher _dfa;
|
||||
|
||||
private EndpointSelectorContext _feature;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
SetupEndpoints();
|
||||
|
||||
SetupRequests();
|
||||
|
||||
_baseline = (TrivialMatcher)SetupMatcher(new TrivialMatcherBuilder());
|
||||
_dfa = (DfaMatcher)SetupMatcher(CreateDfaMatcherBuilder());
|
||||
|
||||
_feature = new EndpointSelectorContext();
|
||||
}
|
||||
|
||||
private void SetupEndpoints()
|
||||
{
|
||||
Endpoints = new RouteEndpoint[10];
|
||||
Endpoints[0] = CreateEndpoint("/another-really-cool-entry");
|
||||
Endpoints[1] = CreateEndpoint("/Some-Entry");
|
||||
Endpoints[2] = CreateEndpoint("/a/path/with/more/segments");
|
||||
Endpoints[3] = CreateEndpoint("/random/name");
|
||||
Endpoints[4] = CreateEndpoint("/random/name2");
|
||||
Endpoints[5] = CreateEndpoint("/random/name3");
|
||||
Endpoints[6] = CreateEndpoint("/random/name4");
|
||||
Endpoints[7] = CreateEndpoint("/plaintext1");
|
||||
Endpoints[8] = CreateEndpoint("/plaintext2");
|
||||
Endpoints[9] = CreateEndpoint("/plaintext");
|
||||
}
|
||||
|
||||
private void SetupRequests()
|
||||
{
|
||||
Requests = new HttpContext[1];
|
||||
Requests[0] = new DefaultHttpContext();
|
||||
Requests[0].RequestServices = CreateServices();
|
||||
Requests[0].Request.Path = "/plaintext";
|
||||
}
|
||||
|
||||
// For this case we're specifically targeting the last entry to hit 'worst case'
|
||||
// performance for the matchers that scale linearly.
|
||||
private Matcher SetupMatcher(MatcherBuilder builder)
|
||||
{
|
||||
builder.AddEndpoint(Endpoints[0]);
|
||||
builder.AddEndpoint(Endpoints[1]);
|
||||
builder.AddEndpoint(Endpoints[2]);
|
||||
builder.AddEndpoint(Endpoints[3]);
|
||||
builder.AddEndpoint(Endpoints[4]);
|
||||
builder.AddEndpoint(Endpoints[5]);
|
||||
builder.AddEndpoint(Endpoints[6]);
|
||||
builder.AddEndpoint(Endpoints[7]);
|
||||
builder.AddEndpoint(Endpoints[8]);
|
||||
builder.AddEndpoint(Endpoints[9]);
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void Baseline()
|
||||
{
|
||||
var httpContext = Requests[0];
|
||||
var path = httpContext.Request.Path.Value;
|
||||
|
||||
var segments = new ReadOnlySpan<PathSegment>(Array.Empty<PathSegment>());
|
||||
|
||||
var candidates = _baseline.FindCandidateSet(path, segments);
|
||||
|
||||
var endpoint = candidates[0].Endpoint;
|
||||
Validate(Requests[0], Endpoints[9], endpoint);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void Dfa()
|
||||
{
|
||||
var httpContext = Requests[0];
|
||||
var path = httpContext.Request.Path.Value;
|
||||
|
||||
Span<PathSegment> segments = stackalloc PathSegment[SegmentCount];
|
||||
var count = FastPathTokenizer.Tokenize(path, segments);
|
||||
|
||||
var candidates = _dfa.FindCandidateSet(httpContext, path, segments.Slice(0, count));
|
||||
|
||||
var endpoint = candidates[0].Endpoint;
|
||||
Validate(Requests[0], Endpoints[9], endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -63,7 +63,7 @@ namespace RoutingSample.Web
|
|||
.ConfigureLogging(b =>
|
||||
{
|
||||
b.AddConsole();
|
||||
b.SetMinimumLevel(LogLevel.Debug);
|
||||
b.SetMinimumLevel(LogLevel.Critical);
|
||||
})
|
||||
.UseContentRoot(Environment.CurrentDirectory)
|
||||
.UseStartup(startupType);
|
||||
|
|
|
|||
|
|
@ -11,18 +11,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
{
|
||||
internal class DefaultEndpointSelector : EndpointSelector
|
||||
{
|
||||
private readonly IEndpointSelectorPolicy[] _selectorPolicies;
|
||||
|
||||
public DefaultEndpointSelector(IEnumerable<MatcherPolicy> matcherPolicies)
|
||||
{
|
||||
if (matcherPolicies == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(matcherPolicies));
|
||||
}
|
||||
|
||||
_selectorPolicies = matcherPolicies.OrderBy(p => p.Order).OfType<IEndpointSelectorPolicy>().ToArray();
|
||||
}
|
||||
|
||||
public override Task SelectAsync(
|
||||
HttpContext httpContext,
|
||||
EndpointSelectorContext context,
|
||||
|
|
@ -43,14 +31,8 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
throw new ArgumentNullException(nameof(candidateSet));
|
||||
}
|
||||
|
||||
if (_selectorPolicies.Length > 0)
|
||||
{
|
||||
// Slow path: we need async to run policies
|
||||
return SelectAsyncSlow(httpContext, context, candidateSet);
|
||||
}
|
||||
|
||||
// Fast path: We can specialize for trivial numbers of candidates since there can
|
||||
// be no ambiguities and we don't need to run policies.
|
||||
// be no ambiguities
|
||||
switch (candidateSet.Count)
|
||||
{
|
||||
case 0:
|
||||
|
|
@ -83,25 +65,6 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task SelectAsyncSlow(
|
||||
HttpContext httpContext,
|
||||
EndpointSelectorContext context,
|
||||
CandidateSet candidateSet)
|
||||
{
|
||||
var selectorPolicies = _selectorPolicies;
|
||||
for (var i = 0; i < selectorPolicies.Length; i++)
|
||||
{
|
||||
await selectorPolicies[i].ApplyAsync(httpContext, context, candidateSet);
|
||||
if (context.Endpoint != null)
|
||||
{
|
||||
// This is a short circuit, the selector chose an endpoint.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessFinalCandidates(httpContext, context, candidateSet);
|
||||
}
|
||||
|
||||
private static void ProcessFinalCandidates(
|
||||
HttpContext httpContext,
|
||||
EndpointSelectorContext context,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
private readonly EndpointSelector _selector;
|
||||
private readonly DfaState[] _states;
|
||||
private readonly int _maxSegmentCount;
|
||||
|
||||
|
||||
public DfaMatcher(ILogger<DfaMatcher> logger, EndpointSelector selector, DfaState[] states, int maxSegmentCount)
|
||||
{
|
||||
_logger = logger;
|
||||
|
|
@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
|
||||
// FindCandidateSet will process the DFA and return a candidate set. This does
|
||||
// some preliminary matching of the URL (mostly the literal segments).
|
||||
var candidates = FindCandidateSet(httpContext, path, segments);
|
||||
var (candidates, policies) = FindCandidateSet(httpContext, path, segments);
|
||||
if (candidates.Length == 0)
|
||||
{
|
||||
if (log)
|
||||
|
|
@ -165,10 +165,16 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
}
|
||||
}
|
||||
|
||||
return _selector.SelectAsync(httpContext, context, candidateSet);
|
||||
if (policies.Length == 0)
|
||||
{
|
||||
// Perf: avoid a state machine if there are no polices
|
||||
return _selector.SelectAsync(httpContext, context, candidateSet);
|
||||
}
|
||||
|
||||
return SelectEndpointWithPoliciesAsync(httpContext, context, policies, candidateSet);
|
||||
}
|
||||
|
||||
internal Candidate[] FindCandidateSet(
|
||||
internal (Candidate[] candidates, IEndpointSelectorPolicy[] policies) FindCandidateSet(
|
||||
HttpContext httpContext,
|
||||
string path,
|
||||
ReadOnlySpan<PathSegment> segments)
|
||||
|
|
@ -190,7 +196,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
policyTransitions = states[destination].PolicyTransitions;
|
||||
}
|
||||
|
||||
return states[destination].Candidates;
|
||||
return (states[destination].Candidates, states[destination].Policies);
|
||||
}
|
||||
|
||||
private void ProcessCaptures(
|
||||
|
|
@ -239,7 +245,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
{
|
||||
for (var i = 0; i < complexSegments.Length; i++)
|
||||
{
|
||||
(var complexSegment, var segmentIndex) = complexSegments[i];
|
||||
(var complexSegment, var segmentIndex) = complexSegments[i];
|
||||
var segment = segments[segmentIndex];
|
||||
var text = path.Substring(segment.Start, segment.Length);
|
||||
if (!RoutePatternMatcher.MatchComplexSegment(complexSegment, text, values))
|
||||
|
|
@ -263,7 +269,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
var constraint = constraints[i];
|
||||
if (!constraint.Value.Match(httpContext, NullRouter.Instance, constraint.Key, values, RouteDirection.IncomingRequest))
|
||||
{
|
||||
Logger.CandidateRejectedByConstraint(_logger, httpContext.Request.Path, endpoint, constraint.Key, constraint.Value, values[constraint.Key]);
|
||||
Logger.CandidateRejectedByConstraint(_logger, httpContext.Request.Path, endpoint, constraint.Key, constraint.Value, values[constraint.Key]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -271,6 +277,26 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
return true;
|
||||
}
|
||||
|
||||
private async Task SelectEndpointWithPoliciesAsync(
|
||||
HttpContext httpContext,
|
||||
EndpointSelectorContext context,
|
||||
IEndpointSelectorPolicy[] policies,
|
||||
CandidateSet candidateSet)
|
||||
{
|
||||
for (var i = 0; i < policies.Length; i++)
|
||||
{
|
||||
var policy = policies[i];
|
||||
await policy.ApplyAsync(httpContext, context, candidateSet);
|
||||
if (context.Endpoint != null)
|
||||
{
|
||||
// This is a short circuit, the selector chose an endpoint.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await _selector.SelectAsync(httpContext, context, candidateSet);
|
||||
}
|
||||
|
||||
internal static class EventIds
|
||||
{
|
||||
public static readonly EventId CandidatesNotFound = new EventId(1000, "CandidatesNotFound");
|
||||
|
|
|
|||
|
|
@ -303,8 +303,10 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
var exitDestination = stateCount - 1;
|
||||
AddNode(root, states, exitDestination);
|
||||
|
||||
// The root state only has a jump table.
|
||||
states[exitDestination] = new DfaState(
|
||||
Array.Empty<Candidate>(),
|
||||
Array.Empty<IEndpointSelectorPolicy>(),
|
||||
JumpTableBuilder.Build(exitDestination, exitDestination, null),
|
||||
null);
|
||||
|
||||
|
|
@ -375,8 +377,30 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
}
|
||||
|
||||
var candidates = CreateCandidates(node.Matches);
|
||||
|
||||
// Perf: most of the time there aren't any endpoint selector policies, create
|
||||
// this lazily.
|
||||
List<IEndpointSelectorPolicy> endpointSelectorPolicies = null;
|
||||
if (node.Matches?.Count > 0)
|
||||
{
|
||||
for (var i = 0; i < _policies.Length; i++)
|
||||
{
|
||||
if (_policies[i] is IEndpointSelectorPolicy endpointSelectorPolicy &&
|
||||
endpointSelectorPolicy.AppliesToEndpoints(node.Matches))
|
||||
{
|
||||
if (endpointSelectorPolicies == null)
|
||||
{
|
||||
endpointSelectorPolicies = new List<IEndpointSelectorPolicy>();
|
||||
}
|
||||
|
||||
endpointSelectorPolicies.Add(endpointSelectorPolicy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
states[currentStateIndex] = new DfaState(
|
||||
candidates,
|
||||
endpointSelectorPolicies?.ToArray() ?? Array.Empty<IEndpointSelectorPolicy>(),
|
||||
JumpTableBuilder.Build(currentDefaultDestination, currentExitDestination, pathEntries),
|
||||
BuildPolicy(currentExitDestination, node.NodeBuilder, policyEntries));
|
||||
|
||||
|
|
@ -617,7 +641,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
for (var j = 0; j < work.Count; j++)
|
||||
{
|
||||
var parent = work[j];
|
||||
if (!nodeBuilder.AppliesToNode(parent.Matches ?? (IReadOnlyList<Endpoint>)Array.Empty<Endpoint>()))
|
||||
if (!nodeBuilder.AppliesToEndpoints(parent.Matches ?? (IReadOnlyList<Endpoint>)Array.Empty<Endpoint>()))
|
||||
{
|
||||
// This node-builder doesn't care about this node, so add it to the list
|
||||
// to be processed by the next node-builder.
|
||||
|
|
|
|||
|
|
@ -9,19 +9,25 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
internal readonly struct DfaState
|
||||
{
|
||||
public readonly Candidate[] Candidates;
|
||||
public readonly IEndpointSelectorPolicy[] Policies;
|
||||
public readonly JumpTable PathTransitions;
|
||||
public readonly PolicyJumpTable PolicyTransitions;
|
||||
|
||||
public DfaState(Candidate[] candidates, JumpTable pathTransitions, PolicyJumpTable policyTransitions)
|
||||
public DfaState(
|
||||
Candidate[] candidates,
|
||||
IEndpointSelectorPolicy[] policies,
|
||||
JumpTable pathTransitions,
|
||||
PolicyJumpTable policyTransitions)
|
||||
{
|
||||
Candidates = candidates;
|
||||
Policies = policies;
|
||||
PathTransitions = pathTransitions;
|
||||
PolicyTransitions = policyTransitions;
|
||||
}
|
||||
|
||||
public string DebuggerToString()
|
||||
{
|
||||
return
|
||||
return
|
||||
$"matches: {Candidates?.Length ?? 0}, " +
|
||||
$"path: ({PathTransitions?.DebuggerToString()}), " +
|
||||
$"policy: ({PolicyTransitions?.DebuggerToString()})";
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
/// </summary>
|
||||
/// <param name="endpoints"></param>
|
||||
/// <returns></returns>
|
||||
public bool AppliesToNode(IReadOnlyList<Endpoint> endpoints)
|
||||
public bool AppliesToEndpoints(IReadOnlyList<Endpoint> endpoints)
|
||||
{
|
||||
if (endpoints == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Matching
|
||||
|
|
@ -14,6 +15,16 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
/// </summary>
|
||||
public interface IEndpointSelectorPolicy
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a value that indicates whether the <see cref="IEndpointSelectorPolicy"/> applies
|
||||
/// to any endpoint in <paramref name="endpoints"/>.
|
||||
/// </summary>
|
||||
/// <param name="endpoints">The set of candidate <see cref="Endpoint"/> values.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the policy applies to any endpoint in <paramref name="endpoints"/>, otherwise <c>false</c>.
|
||||
/// </returns>
|
||||
bool AppliesToEndpoints(IReadOnlyList<Endpoint> endpoints);
|
||||
|
||||
/// <summary>
|
||||
/// Applies the policy to the <see cref="CandidateSet"/>.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
{
|
||||
public interface INodeBuilderPolicy
|
||||
{
|
||||
bool AppliesToNode(IReadOnlyList<Endpoint> endpoints);
|
||||
bool AppliesToEndpoints(IReadOnlyList<Endpoint> endpoints);
|
||||
|
||||
IReadOnlyList<PolicyNodeEdge> GetEdges(IReadOnlyList<Endpoint> endpoints);
|
||||
|
||||
|
|
|
|||
|
|
@ -174,80 +174,6 @@ test: /test3", ex.Message);
|
|||
Assert.Null(context.Endpoint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SelectAsync_RunsEndpointSelectorPolicies()
|
||||
{
|
||||
// Arrange
|
||||
var endpoints = new RouteEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), CreateEndpoint("/test3"), };
|
||||
var scores = new int[] { 0, 0, 1 };
|
||||
var candidateSet = CreateCandidateSet(endpoints, scores);
|
||||
|
||||
var policy = new Mock<MatcherPolicy>();
|
||||
policy
|
||||
.As<IEndpointSelectorPolicy>()
|
||||
.Setup(p => p.ApplyAsync(It.IsAny<HttpContext>(), It.IsAny<EndpointSelectorContext>(), It.IsAny<CandidateSet>()))
|
||||
.Returns<HttpContext, EndpointSelectorContext, CandidateSet>((c, f, cs) =>
|
||||
{
|
||||
cs.SetValidity(1, false);
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
||||
candidateSet.SetValidity(0, false);
|
||||
candidateSet.SetValidity(1, true);
|
||||
candidateSet.SetValidity(2, true);
|
||||
|
||||
var (httpContext, context) = CreateContext();
|
||||
var selector = CreateSelector(policy.Object);
|
||||
|
||||
// Act
|
||||
await selector.SelectAsync(httpContext, context, candidateSet);
|
||||
|
||||
// Assert
|
||||
Assert.Same(endpoints[2], context.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<EndpointSelectorContext>(), It.IsAny<CandidateSet>()))
|
||||
.Returns<HttpContext, EndpointSelectorContext, 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<EndpointSelectorContext>(), It.IsAny<CandidateSet>()))
|
||||
.Throws(new InvalidOperationException());
|
||||
|
||||
candidateSet.SetValidity(0, false);
|
||||
candidateSet.SetValidity(1, true);
|
||||
candidateSet.SetValidity(2, true);
|
||||
|
||||
var (httpContext, context) = CreateContext();
|
||||
var selector = CreateSelector(policy1.Object, policy2.Object);
|
||||
|
||||
// Act
|
||||
await selector.SelectAsync(httpContext, context, candidateSet);
|
||||
|
||||
// Assert
|
||||
Assert.Same(endpoints[0], context.Endpoint);
|
||||
}
|
||||
|
||||
private static (HttpContext httpContext, EndpointSelectorContext context) CreateContext()
|
||||
{
|
||||
var context = new EndpointSelectorContext();
|
||||
|
|
@ -273,9 +199,9 @@ test: /test3", ex.Message);
|
|||
return new CandidateSet(endpoints, new RouteValueDictionary[endpoints.Length], scores);
|
||||
}
|
||||
|
||||
private static DefaultEndpointSelector CreateSelector(params MatcherPolicy[] policies)
|
||||
private static DefaultEndpointSelector CreateSelector()
|
||||
{
|
||||
return new DefaultEndpointSelector(policies);
|
||||
return new DefaultEndpointSelector();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1013,7 +1013,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
|
||||
public IComparer<Endpoint> Comparer => EndpointMetadataComparer<TestMetadata1>.Default;
|
||||
|
||||
public bool AppliesToNode(IReadOnlyList<Endpoint> endpoints)
|
||||
public bool AppliesToEndpoints(IReadOnlyList<Endpoint> endpoints)
|
||||
{
|
||||
return endpoints.Any(e => e.Metadata.GetMetadata<TestMetadata1>() != null);
|
||||
}
|
||||
|
|
@ -1052,7 +1052,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
|
||||
public IComparer<Endpoint> Comparer => EndpointMetadataComparer<TestMetadata2>.Default;
|
||||
|
||||
public bool AppliesToNode(IReadOnlyList<Endpoint> endpoints)
|
||||
public bool AppliesToEndpoints(IReadOnlyList<Endpoint> endpoints)
|
||||
{
|
||||
return endpoints.Any(e => e.Metadata.GetMetadata<TestMetadata2>() != null);
|
||||
}
|
||||
|
|
@ -1077,7 +1077,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
|
||||
public IComparer<Endpoint> Comparer => EndpointMetadataComparer<TestMetadata1>.Default;
|
||||
|
||||
public bool AppliesToNode(IReadOnlyList<Endpoint> endpoints)
|
||||
public bool AppliesToEndpoints(IReadOnlyList<Endpoint> endpoints)
|
||||
{
|
||||
return endpoints.Any(e => e.Metadata.GetMetadata<TestMetadata1>() != null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
|
@ -28,13 +29,25 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
template);
|
||||
}
|
||||
|
||||
private Matcher CreateDfaMatcher(EndpointDataSource dataSource, EndpointSelector endpointSelector = null, ILoggerFactory loggerFactory = null)
|
||||
private Matcher CreateDfaMatcher(
|
||||
EndpointDataSource dataSource,
|
||||
MatcherPolicy[] policies = null,
|
||||
EndpointSelector endpointSelector = null,
|
||||
ILoggerFactory loggerFactory = null)
|
||||
{
|
||||
var serviceCollection = new ServiceCollection()
|
||||
.AddLogging()
|
||||
.AddOptions()
|
||||
.AddRouting();
|
||||
|
||||
if (policies != null)
|
||||
{
|
||||
for (var i = 0; i < policies.Length; i++)
|
||||
{
|
||||
serviceCollection.AddSingleton<MatcherPolicy>(policies[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (endpointSelector != null)
|
||||
{
|
||||
serviceCollection.AddSingleton<EndpointSelector>(endpointSelector);
|
||||
|
|
@ -152,7 +165,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
endpoint2
|
||||
});
|
||||
|
||||
var matcher = CreateDfaMatcher(endpointDataSource, endpointSelector.Object);
|
||||
var matcher = CreateDfaMatcher(endpointDataSource, endpointSelector: endpointSelector.Object);
|
||||
|
||||
var (httpContext, context) = CreateContext();
|
||||
httpContext.Request.Path = "/Teams";
|
||||
|
|
@ -331,6 +344,126 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MatchAsync_RunsApplicableEndpointSelectorPolicies()
|
||||
{
|
||||
// Arrange
|
||||
var dataSource = new DefaultEndpointDataSource(new List<Endpoint>
|
||||
{
|
||||
CreateEndpoint("/test/{id:alpha}", 0),
|
||||
CreateEndpoint("/test/{id:int}", 0),
|
||||
CreateEndpoint("/test/{id}", 0),
|
||||
});
|
||||
|
||||
var policy = new Mock<MatcherPolicy>();
|
||||
policy
|
||||
.As<IEndpointSelectorPolicy>()
|
||||
.Setup(p => p.AppliesToEndpoints(It.IsAny<IReadOnlyList<Endpoint>>())).Returns(true);
|
||||
policy
|
||||
.As<IEndpointSelectorPolicy>()
|
||||
.Setup(p => p.ApplyAsync(It.IsAny<HttpContext>(), It.IsAny<EndpointSelectorContext>(), It.IsAny<CandidateSet>()))
|
||||
.Returns<HttpContext, EndpointSelectorContext, CandidateSet>((c, f, cs) =>
|
||||
{
|
||||
cs.SetValidity(1, false);
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
||||
var matcher = CreateDfaMatcher(dataSource, policies: new[] { policy.Object, });
|
||||
|
||||
var (httpContext, context) = CreateContext();
|
||||
httpContext.Request.Path = "/test/17";
|
||||
|
||||
// Act
|
||||
await matcher.MatchAsync(httpContext, context);
|
||||
|
||||
// Assert
|
||||
Assert.Same(dataSource.Endpoints[2], context.Endpoint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MatchAsync_SkipsNonApplicableEndpointSelectorPolicies()
|
||||
{
|
||||
// Arrange
|
||||
var dataSource = new DefaultEndpointDataSource(new List<Endpoint>
|
||||
{
|
||||
CreateEndpoint("/test/{id:alpha}", 0),
|
||||
CreateEndpoint("/test/{id:int}", 0),
|
||||
CreateEndpoint("/test/{id}", 0),
|
||||
});
|
||||
|
||||
var policy = new Mock<MatcherPolicy>();
|
||||
policy
|
||||
.As<IEndpointSelectorPolicy>()
|
||||
.Setup(p => p.AppliesToEndpoints(It.IsAny<IReadOnlyList<Endpoint>>())).Returns(false);
|
||||
policy
|
||||
.As<IEndpointSelectorPolicy>()
|
||||
.Setup(p => p.ApplyAsync(It.IsAny<HttpContext>(), It.IsAny<EndpointSelectorContext>(), It.IsAny<CandidateSet>()))
|
||||
.Returns<HttpContext, EndpointSelectorContext, CandidateSet>((c, f, cs) =>
|
||||
{
|
||||
throw null; // Won't be called.
|
||||
});
|
||||
|
||||
var matcher = CreateDfaMatcher(dataSource, policies: new[] { policy.Object, });
|
||||
|
||||
var (httpContext, context) = CreateContext();
|
||||
httpContext.Request.Path = "/test/17";
|
||||
|
||||
// Act
|
||||
await matcher.MatchAsync(httpContext, context);
|
||||
|
||||
// Assert
|
||||
Assert.Same(dataSource.Endpoints[1], context.Endpoint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MatchAsync_RunsEndpointSelectorPolicies_CanShortCircuit()
|
||||
{
|
||||
// Arrange
|
||||
var dataSource = new DefaultEndpointDataSource(new List<Endpoint>
|
||||
{
|
||||
CreateEndpoint("/test/{id:alpha}", 0),
|
||||
CreateEndpoint("/test/{id:int}", 0),
|
||||
CreateEndpoint("/test/{id}", 0),
|
||||
});
|
||||
|
||||
var policy1 = new Mock<MatcherPolicy>();
|
||||
policy1
|
||||
.As<IEndpointSelectorPolicy>()
|
||||
.Setup(p => p.AppliesToEndpoints(It.IsAny<IReadOnlyList<Endpoint>>())).Returns(true);
|
||||
policy1
|
||||
.As<IEndpointSelectorPolicy>()
|
||||
.Setup(p => p.ApplyAsync(It.IsAny<HttpContext>(), It.IsAny<EndpointSelectorContext>(), It.IsAny<CandidateSet>()))
|
||||
.Returns<HttpContext, EndpointSelectorContext, 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.AppliesToEndpoints(It.IsAny<IReadOnlyList<Endpoint>>())).Returns(true);
|
||||
policy2
|
||||
.As<IEndpointSelectorPolicy>()
|
||||
.Setup(p => p.ApplyAsync(It.IsAny<HttpContext>(), It.IsAny<EndpointSelectorContext>(), It.IsAny<CandidateSet>()))
|
||||
.Throws(new InvalidOperationException());
|
||||
|
||||
var matcher = CreateDfaMatcher(dataSource, policies: new[] { policy1.Object, policy2.Object, });
|
||||
|
||||
var (httpContext, context) = CreateContext();
|
||||
httpContext.Request.Path = "/test/17";
|
||||
|
||||
// Act
|
||||
await matcher.MatchAsync(httpContext, context);
|
||||
|
||||
// Assert
|
||||
Assert.Same(dataSource.Endpoints[0], context.Endpoint);
|
||||
}
|
||||
|
||||
private (HttpContext httpContext, EndpointSelectorContext context) CreateContext()
|
||||
{
|
||||
var context = new EndpointSelectorContext();
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
var policy = CreatePolicy();
|
||||
|
||||
// Act
|
||||
var result = policy.AppliesToNode(endpoints);
|
||||
var result = policy.AppliesToEndpoints(endpoints);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
|
|
@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
var policy = CreatePolicy();
|
||||
|
||||
// Act
|
||||
var result = policy.AppliesToNode(endpoints);
|
||||
var result = policy.AppliesToEndpoints(endpoints);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
|
|
@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
var policy = CreatePolicy();
|
||||
|
||||
// Act
|
||||
var result = policy.AppliesToNode(endpoints);
|
||||
var result = policy.AppliesToEndpoints(endpoints);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
|
||||
public override Matcher Build()
|
||||
{
|
||||
var selector = new DefaultEndpointSelector(Array.Empty<MatcherPolicy>());
|
||||
var selector = new DefaultEndpointSelector();
|
||||
|
||||
var groups = _endpoints
|
||||
.GroupBy(e => (e.Order, e.RoutePattern.InboundPrecedence, e.RoutePattern.RawText))
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.Routing.Matching
|
|||
new DefaultObjectPool<UriBuildingContext>(new UriBuilderContextPooledObjectPolicy()),
|
||||
new DefaultInlineConstraintResolver(Options.Create(new RouteOptions()), new TestServiceProvider()));
|
||||
|
||||
var selector = new DefaultEndpointSelector(Array.Empty<MatcherPolicy>());
|
||||
var selector = new DefaultEndpointSelector();
|
||||
|
||||
var groups = _endpoints
|
||||
.GroupBy(e => (e.Order, e.RoutePattern.InboundPrecedence, e.RoutePattern.RawText))
|
||||
|
|
|
|||
Loading…
Reference in New Issue