Merge pull request #615 from dotnet-maestro-bot/merge/release/2.2-to-master

[automated] Merge branch 'release/2.2' => 'master'
This commit is contained in:
Ryan Nowak 2018-07-14 17:28:48 -07:00 committed by GitHub
commit 4334feacb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 55527 additions and 22572 deletions

View File

@ -95,7 +95,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers
_indexes = indexes;
}
public override unsafe int GetDestination(string path, PathSegment segment)
public override int GetDestination(string path, PathSegment segment)
{
if (segment.Length == 0)
{

View File

@ -0,0 +1,28 @@
// 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;
namespace Microsoft.AspNetCore.Routing.Matchers
{
// This is not yet fleshed out - consider this part of the
// work-in-progress definition of CandidateSet.
internal readonly struct Candidate
{
public readonly MatcherEndpoint Endpoint;
public readonly string[] Parameters;
public Candidate(MatcherEndpoint endpoint)
{
Endpoint = endpoint;
Parameters = Array.Empty<string>();
}
public Candidate(MatcherEndpoint endpoint, string[] parameters)
{
Endpoint = endpoint;
Parameters = parameters;
}
}
}

View File

@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers
return Primes[Primes.Length - 1];
}
public override unsafe int GetDestination(string path, PathSegment segment)
public override int GetDestination(string path, PathSegment segment)
{
if (segment.Length == 0)
{

View File

@ -5,7 +5,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers
{
public abstract class FastPathTokenizerBenchmarkBase
{
internal unsafe void NaiveBaseline(string path, PathSegment * segments, int maxCount)
internal unsafe void NaiveBaseline(string path, PathSegment* segments, int maxCount)
{
int count = 0;
int start = 1; // Paths always start with a leading /

View File

@ -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 BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
@ -21,12 +22,12 @@ namespace Microsoft.AspNetCore.Routing.Matchers
}
[Benchmark]
public unsafe void Implementation()
public void Implementation()
{
var path = Input;
var segments = stackalloc PathSegment[MaxCount];
Span<PathSegment> segments = stackalloc PathSegment[MaxCount];
FastPathTokenizer.Tokenize(path, segments, MaxCount);
FastPathTokenizer.Tokenize(path, segments);
}
}
}

View File

@ -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 BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
@ -25,12 +26,12 @@ namespace Microsoft.AspNetCore.Routing.Matchers
}
[Benchmark]
public unsafe void Implementation()
public void Implementation()
{
var path = Input;
var segments = stackalloc PathSegment[MaxCount];
Span<PathSegment> segments = stackalloc PathSegment[MaxCount];
FastPathTokenizer.Tokenize(path, segments, MaxCount);
FastPathTokenizer.Tokenize(path, segments);
}
}
}

View File

@ -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 BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
@ -21,12 +22,12 @@ namespace Microsoft.AspNetCore.Routing.Matchers
}
[Benchmark]
public unsafe void Implementation()
public void Implementation()
{
var path = Input;
var segments = stackalloc PathSegment[MaxCount];
Span<PathSegment> segments = stackalloc PathSegment[MaxCount];
FastPathTokenizer.Tokenize(path, segments, MaxCount);
FastPathTokenizer.Tokenize(path, segments);
}
}
}

View File

@ -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 BenchmarkDotNet.Attributes;
namespace Microsoft.AspNetCore.Routing.Matchers
@ -21,12 +22,12 @@ namespace Microsoft.AspNetCore.Routing.Matchers
}
[Benchmark]
public unsafe void Implementation()
public void Implementation()
{
var path = Input;
var segments = stackalloc PathSegment[MaxCount];
Span<PathSegment> segments = stackalloc PathSegment[MaxCount];
FastPathTokenizer.Tokenize(path, segments, MaxCount);
FastPathTokenizer.Tokenize(path, segments);
}
}
}

View File

@ -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.Matchers
{
// This code was generated by the Swaggatherer
public partial class GithubMatcherBenchmark : MatcherBenchmarkBase
{
private const int EndpointCount = 155;
private void SetupEndpoints()
{
_endpoints = new MatcherEndpoint[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();
}
}
}

View File

@ -1,20 +1,18 @@
// 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.Matchers
{
// Generated from https://github.com/Azure/azure-rest-api-specs
public partial class AzureMatcherBenchmark : MatcherBenchmarkBase
public partial class MatcherAzureBenchmark : MatcherBenchmarkBase
{
private const int SampleCount = 100;
private BarebonesMatcher _baseline;
private Matcher _dfa;
private Matcher _route;
private Matcher _tree;
private int[] _samples;
@ -33,7 +31,6 @@ namespace Microsoft.AspNetCore.Routing.Matchers
_baseline = (BarebonesMatcher)SetupMatcher(new BarebonesMatcherBuilder());
_dfa = SetupMatcher(new DfaMatcherBuilder());
_route = SetupMatcher(new RouteMatcherBuilder());
_tree = SetupMatcher(new TreeRouterMatcherBuilder());
_feature = new EndpointFeature();
@ -46,9 +43,9 @@ namespace Microsoft.AspNetCore.Routing.Matchers
for (var i = 0; i < SampleCount; i++)
{
var sample = _samples[i];
var httpContext = _requests[sample];
await _baseline._matchers[sample].MatchAsync(httpContext, feature);
Validate(httpContext, _endpoints[sample], feature.Endpoint);
var httpContext = Requests[sample];
await _baseline.Matchers[sample].MatchAsync(httpContext, feature);
Validate(httpContext, Endpoints[sample], feature.Endpoint);
}
}
@ -59,26 +56,9 @@ namespace Microsoft.AspNetCore.Routing.Matchers
for (var i = 0; i < SampleCount; i++)
{
var sample = _samples[i];
var httpContext = _requests[sample];
var httpContext = Requests[sample];
await _dfa.MatchAsync(httpContext, feature);
Validate(httpContext, _endpoints[sample], feature.Endpoint);
}
}
[Benchmark(OperationsPerInvoke = SampleCount)]
public async Task LegacyRoute()
{
var feature = _feature;
for (var i = 0; i < SampleCount; i++)
{
var sample = _samples[i];
var httpContext = _requests[sample];
// This is required to make the legacy router implementation work with dispatcher.
httpContext.Features.Set<IEndpointFeature>(feature);
await _route.MatchAsync(httpContext, feature);
Validate(httpContext, _endpoints[sample], feature.Endpoint);
Validate(httpContext, Endpoints[sample], feature.Endpoint);
}
}
@ -89,13 +69,13 @@ namespace Microsoft.AspNetCore.Routing.Matchers
for (var i = 0; i < SampleCount; i++)
{
var sample = _samples[i];
var httpContext = _requests[sample];
var httpContext = Requests[sample];
// This is required to make the legacy router implementation work with dispatcher.
httpContext.Features.Set<IEndpointFeature>(feature);
await _tree.MatchAsync(httpContext, feature);
Validate(httpContext, _endpoints[sample], feature.Endpoint);
Validate(httpContext, Endpoints[sample], feature.Endpoint);
}
}
}

View File

@ -14,18 +14,18 @@ namespace Microsoft.AspNetCore.Routing.Matchers
{
public abstract class MatcherBenchmarkBase
{
internal MatcherEndpoint[] _endpoints;
internal HttpContext[] _requests;
private protected MatcherEndpoint[] Endpoints;
private protected HttpContext[] Requests;
// The older routing implementations retrieve services when they first execute.
internal static IServiceProvider CreateServices()
private protected static IServiceProvider CreateServices()
{
var services = new ServiceCollection();
services.AddLogging();
return services.BuildServiceProvider();
}
internal static MatcherEndpoint CreateEndpoint(string template, string httpMethod = null)
private protected static MatcherEndpoint CreateEndpoint(string template, string httpMethod = null)
{
var metadata = new List<object>();
if (httpMethod != null)
@ -40,11 +40,11 @@ namespace Microsoft.AspNetCore.Routing.Matchers
new RouteValueDictionary(),
new List<MatchProcessorReference>(),
0,
EndpointMetadataCollection.Empty,
new EndpointMetadataCollection(metadata),
template);
}
internal static int[] SampleRequests(int endpointCount, int count)
private protected static int[] SampleRequests(int endpointCount, int count)
{
// This isn't very high tech, but it's at least regular distribution.
// We sort the route templates by precedence, so this should result in
@ -67,12 +67,12 @@ namespace Microsoft.AspNetCore.Routing.Matchers
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal void Validate(HttpContext httpContext, Endpoint expected, Endpoint actual)
private protected void Validate(HttpContext httpContext, Endpoint expected, Endpoint actual)
{
if (!object.ReferenceEquals(expected, actual))
{
var message = new StringBuilder();
message.AppendLine($"Validation failed for request {Array.IndexOf(_requests, httpContext)}");
message.AppendLine($"Validation failed for request {Array.IndexOf(Requests, httpContext)}");
message.AppendLine($"{httpContext.Request.Method} {httpContext.Request.Path}");
message.AppendLine($"expected: '{((MatcherEndpoint)expected)?.DisplayName ?? "null"}'");
message.AppendLine($"actual: '{((MatcherEndpoint)actual)?.DisplayName ?? "null"}'");

View File

@ -1,7 +1,6 @@
// 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;
@ -9,11 +8,10 @@ namespace Microsoft.AspNetCore.Routing.Matchers
{
// Generated from https://github.com/APIs-guru/openapi-directory
// Use https://editor2.swagger.io/ to convert from yaml to json-
public partial class GithubMatcherBenchmark : MatcherBenchmarkBase
public partial class MatcherGithubBenchmark : MatcherBenchmarkBase
{
private BarebonesMatcher _baseline;
private Matcher _dfa;
private Matcher _route;
private Matcher _tree;
private EndpointFeature _feature;
@ -27,7 +25,6 @@ namespace Microsoft.AspNetCore.Routing.Matchers
_baseline = (BarebonesMatcher)SetupMatcher(new BarebonesMatcherBuilder());
_dfa = SetupMatcher(new DfaMatcherBuilder());
_route = SetupMatcher(new RouteMatcherBuilder());
_tree = SetupMatcher(new TreeRouterMatcherBuilder());
_feature = new EndpointFeature();
@ -39,9 +36,9 @@ namespace Microsoft.AspNetCore.Routing.Matchers
var feature = _feature;
for (var i = 0; i < EndpointCount; i++)
{
var httpContext = _requests[i];
await _baseline._matchers[i].MatchAsync(httpContext, feature);
Validate(httpContext, _endpoints[i], feature.Endpoint);
var httpContext = Requests[i];
await _baseline.Matchers[i].MatchAsync(httpContext, feature);
Validate(httpContext, Endpoints[i], feature.Endpoint);
}
}
@ -51,25 +48,9 @@ namespace Microsoft.AspNetCore.Routing.Matchers
var feature = _feature;
for (var i = 0; i < EndpointCount; i++)
{
var httpContext = _requests[i];
var httpContext = Requests[i];
await _dfa.MatchAsync(httpContext, feature);
Validate(httpContext, _endpoints[i], feature.Endpoint);
}
}
[Benchmark(OperationsPerInvoke = EndpointCount)]
public async Task LegacyRoute()
{
var feature = _feature;
for (var i = 0; i < EndpointCount; i++)
{
var httpContext = _requests[i];
// This is required to make the legacy router implementation work with dispatcher.
httpContext.Features.Set<IEndpointFeature>(feature);
await _route.MatchAsync(httpContext, feature);
Validate(httpContext, _endpoints[i], feature.Endpoint);
Validate(httpContext, Endpoints[i], feature.Endpoint);
}
}
@ -79,13 +60,13 @@ namespace Microsoft.AspNetCore.Routing.Matchers
var feature = _feature;
for (var i = 0; i < EndpointCount; i++)
{
var httpContext = _requests[i];
var httpContext = Requests[i];
// This is required to make the legacy router implementation work with dispatcher.
httpContext.Features.Set<IEndpointFeature>(feature);
await _tree.MatchAsync(httpContext, feature);
Validate(httpContext, _endpoints[i], feature.Endpoint);
Validate(httpContext, Endpoints[i], feature.Endpoint);
}
}
}

View File

@ -0,0 +1,71 @@
// 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.Matchers
{
// Generated from https://github.com/Azure/azure-rest-api-specs
public partial class MatcherSelectCandidatesAzureBenchmark : MatcherBenchmarkBase
{
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(new DfaMatcherBuilder());
}
[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].SelectCandidates(path, segments);
var endpoint = candidates.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[FastPathTokenizer.DefaultSegmentCount];
var count = FastPathTokenizer.Tokenize(path, segments);
var candidates = _dfa.SelectCandidates(path, segments.Slice(0, count));
var endpoint = candidates.Candidates[0].Endpoint;
Validate(httpContext, Endpoints[sample], endpoint);
}
}
}
}

View File

@ -0,0 +1,63 @@
// 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.Matchers
{
// Generated from https://github.com/APIs-guru/openapi-directory
// Use https://editor2.swagger.io/ to convert from yaml to json-
public partial class MatcherSelectCandidatesGithubBenchmark : MatcherBenchmarkBase
{
private BarebonesMatcher _baseline;
private DfaMatcher _dfa;
[GlobalSetup]
public void Setup()
{
SetupEndpoints();
SetupRequests();
_baseline = (BarebonesMatcher)SetupMatcher(new BarebonesMatcherBuilder());
_dfa = (DfaMatcher)SetupMatcher(new DfaMatcherBuilder());
}
[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].SelectCandidates(path, segments);
var endpoint = candidates.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[FastPathTokenizer.DefaultSegmentCount];
var count = FastPathTokenizer.Tokenize(path, segments);
var candidates = _dfa.SelectCandidates(path, segments.Slice(0, count));
var endpoint = candidates.Candidates[0].Endpoint;
Validate(httpContext, Endpoints[i], endpoint);
}
}
}
}

View File

@ -0,0 +1,959 @@
// 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.Matchers
{
// This code was generated by the Swaggatherer
public partial class MatcherSelectCandidatesGithubBenchmark : MatcherBenchmarkBase
{
private const int EndpointCount = 155;
private void SetupEndpoints()
{
Endpoints = new MatcherEndpoint[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();
}
}
}

View File

@ -0,0 +1,63 @@
// 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.Matchers
{
public class MatcherSelectCandidatesSingleEntryBenchmark : MatcherBenchmarkBase
{
private TrivialMatcher _baseline;
private DfaMatcher _dfa;
[GlobalSetup]
public void Setup()
{
Endpoints = new MatcherEndpoint[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(new DfaMatcherBuilder());
}
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.SelectCandidates(path, segments);
var endpoint = candidates.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[FastPathTokenizer.DefaultSegmentCount];
var count = FastPathTokenizer.Tokenize(path, segments);
var candidates = _dfa.SelectCandidates(path, segments.Slice(0, count));
var endpoint = candidates.Candidates[0].Endpoint;
Validate(Requests[0], Endpoints[0], endpoint);
}
}
}

View File

@ -0,0 +1,99 @@
// 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.Matchers
{
public class MatcherSelectCandidatesSmallEntryCountBenchmark : MatcherBenchmarkBase
{
private TrivialMatcher _baseline;
private DfaMatcher _dfa;
private EndpointFeature _feature;
[GlobalSetup]
public void Setup()
{
SetupEndpoints();
SetupRequests();
_baseline = (TrivialMatcher)SetupMatcher(new TrivialMatcherBuilder());
_dfa = (DfaMatcher)SetupMatcher(new DfaMatcherBuilder());
_feature = new EndpointFeature();
}
private void SetupEndpoints()
{
Endpoints = new MatcherEndpoint[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.SelectCandidates(path, segments);
var endpoint = candidates.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[FastPathTokenizer.DefaultSegmentCount];
var count = FastPathTokenizer.Tokenize(path, segments);
var candidates = _dfa.SelectCandidates(path, segments.Slice(0, count));
var endpoint = candidates.Candidates[0].Endpoint;
Validate(Requests[0], Endpoints[9], endpoint);
}
}
}

View File

@ -0,0 +1,94 @@
// 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.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
{
// Just like TechEmpower Plaintext
public partial class MatcherSingleEntryBenchmark : MatcherBenchmarkBase
{
private const int SampleCount = 100;
private BarebonesMatcher _baseline;
private Matcher _dfa;
private Matcher _route;
private Matcher _tree;
private EndpointFeature _feature;
[GlobalSetup]
public void Setup()
{
Endpoints = new MatcherEndpoint[1];
Endpoints[0] = CreateEndpoint("/plaintext");
Requests = new HttpContext[1];
Requests[0] = new DefaultHttpContext();
Requests[0].RequestServices = CreateServices();
Requests[0].Request.Path = "/plaintext";
_baseline = (BarebonesMatcher)SetupMatcher(new BarebonesMatcherBuilder());
_dfa = SetupMatcher(new DfaMatcherBuilder());
_route = SetupMatcher(new RouteMatcherBuilder());
_tree = SetupMatcher(new TreeRouterMatcherBuilder());
_feature = new EndpointFeature();
}
private Matcher SetupMatcher(MatcherBuilder builder)
{
builder.AddEndpoint(Endpoints[0]);
return builder.Build();
}
[Benchmark(Baseline = true)]
public async Task Baseline()
{
var feature = _feature;
var httpContext = Requests[0];
await _baseline.MatchAsync(httpContext, feature);
Validate(httpContext, Endpoints[0], feature.Endpoint);
}
[Benchmark]
public async Task Dfa()
{
var feature = _feature;
var httpContext = Requests[0];
await _dfa.MatchAsync(httpContext, feature);
Validate(httpContext, Endpoints[0], feature.Endpoint);
}
[Benchmark]
public async Task LegacyTreeRouter()
{
var feature = _feature;
var httpContext = Requests[0];
// This is required to make the legacy router implementation work with dispatcher.
httpContext.Features.Set<IEndpointFeature>(feature);
await _tree.MatchAsync(httpContext, feature);
Validate(httpContext, Endpoints[0], feature.Endpoint);
}
[Benchmark]
public async Task LegacyRouter()
{
var feature = _feature;
var httpContext = Requests[0];
// This is required to make the legacy router implementation work with dispatcher.
httpContext.Features.Set<IEndpointFeature>(feature);
await _route.MatchAsync(httpContext, feature);
Validate(httpContext, Endpoints[0], feature.Endpoint);
}
}
}

View File

@ -1,84 +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.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
{
public class SingleEntryMatcherBenchmark : MatcherBenchmarkBase
{
private Matcher _baseline;
private Matcher _dfa;
private Matcher _route;
private Matcher _tree;
private EndpointFeature _feature;
[GlobalSetup]
public void Setup()
{
_endpoints = new MatcherEndpoint[1];
_endpoints[0] = CreateEndpoint("/plaintext");
_requests = new HttpContext[1];
_requests[0] = new DefaultHttpContext();
_requests[0].RequestServices = CreateServices();
_requests[0].Request.Path = "/plaintext";
_baseline = SetupMatcher(new TrivialMatcherBuilder());
_dfa = SetupMatcher(new DfaMatcherBuilder());
_route = SetupMatcher(new RouteMatcherBuilder());
_tree = SetupMatcher(new TreeRouterMatcherBuilder());
_feature = new EndpointFeature();
}
private Matcher SetupMatcher(MatcherBuilder builder)
{
builder.AddEndpoint(_endpoints[0]);
return builder.Build();
}
[Benchmark(Baseline = true)]
public async Task Baseline()
{
var feature = _feature;
await _baseline.MatchAsync(_requests[0], feature);
Validate(_requests[0], _endpoints[0], feature.Endpoint);
}
[Benchmark]
public async Task Dfa()
{
var feature = _feature;
await _dfa.MatchAsync(_requests[0], feature);
Validate(_requests[0], _endpoints[0], feature.Endpoint);
}
[Benchmark]
public async Task LegacyRoute()
{
var feature = _feature;
// This is required to make the legacy router implementation work with dispatcher.
_requests[0].Features.Set<IEndpointFeature>(feature);
await _route.MatchAsync(_requests[0], feature);
Validate(_requests[0], _endpoints[0], feature.Endpoint);
}
[Benchmark]
public async Task LegacyTreeRouter()
{
var feature = _feature;
// This is required to make the legacy router implementation work with dispatcher.
_requests[0].Features.Set<IEndpointFeature>(feature);
await _tree.MatchAsync(_requests[0], feature);
Validate(_requests[0], _endpoints[0], feature.Endpoint);
}
}
}

View File

@ -1,114 +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.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing.Matchers
{
public class SmallEntryCountLiteralMatcherBenchark : MatcherBenchmarkBase
{
private Matcher _baseline;
private Matcher _dfa;
private Matcher _route;
private Matcher _tree;
private EndpointFeature _feature;
[GlobalSetup]
public void Setup()
{
SetupEndpoints();
SetupRequests();
_baseline = SetupMatcher(new TrivialMatcherBuilder());
_dfa = SetupMatcher(new DfaMatcherBuilder());
_route = SetupMatcher(new RouteMatcherBuilder());
_tree = SetupMatcher(new TreeRouterMatcherBuilder());
_feature = new EndpointFeature();
}
private void SetupEndpoints()
{
_endpoints = new MatcherEndpoint[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 async Task Baseline()
{
var feature = _feature;
await _baseline.MatchAsync(_requests[0], feature);
Validate(_requests[0], _endpoints[9], feature.Endpoint);
}
[Benchmark]
public async Task Dfa()
{
var feature = _feature;
await _dfa.MatchAsync(_requests[0], feature);
Validate(_requests[0], _endpoints[9], feature.Endpoint);
}
[Benchmark]
public async Task LegacyRoute()
{
var feature = _feature;
// This is required to make the legacy router implementation work with dispatcher.
_requests[0].Features.Set<IEndpointFeature>(feature);
await _route.MatchAsync(_requests[0], feature);
Validate(_requests[0], _endpoints[9], feature.Endpoint);
}
[Benchmark]
public async Task LegacyTreeRouter()
{
var feature = _feature;
// This is required to make the legacy router implementation work with dispatcher.
_requests[0].Features.Set<IEndpointFeature>(feature);
await _tree.MatchAsync(_requests[0], feature);
Validate(_requests[0], _endpoints[9], feature.Endpoint);
}
}
}

View File

@ -10,16 +10,23 @@ namespace Microsoft.AspNetCore.Routing.Matchers
// A test-only matcher implementation - used as a baseline for simpler
// perf tests. The idea with this matcher is that we can cheat on the requirements
// to establish a lower bound for perf comparisons.
internal class TrivialMatcher : Matcher
internal sealed class TrivialMatcher : Matcher
{
private readonly MatcherEndpoint _endpoint;
private readonly CandidateSet _candidates;
public TrivialMatcher(MatcherEndpoint endpoint)
{
_endpoint = endpoint;
_candidates = new CandidateSet(
new Candidate[] { new Candidate(endpoint), },
// Single candidate group that contains one entry.
CandidateSet.MakeGroups(new[] { 1 }));
}
public override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature)
public sealed override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature)
{
if (httpContext == null)
{
@ -40,5 +47,16 @@ namespace Microsoft.AspNetCore.Routing.Matchers
return Task.CompletedTask;
}
// This is here so this can be tested alongside DFA matcher.
internal CandidateSet SelectCandidates(string path, ReadOnlySpan<PathSegment> segments)
{
if (string.Equals(_endpoint.Template, path, StringComparison.OrdinalIgnoreCase))
{
return _candidates;
}
return CandidateSet.Empty;
}
}
}

View File

@ -18,6 +18,7 @@
for perf comparisons.
-->
<ItemGroup>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matchers\CandidateSet.cs" Link="Matchers\CandidateSet.cs" />
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matchers\MatcherBuilder.cs">
<Link>Matchers\MatcherBuilder.cs</Link>
</Compile>
@ -33,6 +34,7 @@
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matchers\DfaMatcherBuilder.cs">
<Link>Matchers\DfaMatcherBuilder.cs</Link>
</Compile>
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matchers\MatcherBuilderEntry.cs" Link="Matchers\MatcherBuilderEntry.cs" />
<Compile Include="..\..\test\Microsoft.AspNetCore.Routing.Tests\Matchers\RouteMatcher.cs">
<Link>Matchers\RouteMatcher.cs</Link>
</Compile>

View File

@ -10,10 +10,14 @@ namespace Microsoft.AspNetCore.Builder
{
public static class DispatcherApplicationBuilderExtensions
{
private const string DispatcherRegisteredKey = "__DispatcherMiddlewareRegistered";
public static IApplicationBuilder UseDispatcher(this IApplicationBuilder builder)
{
VerifyDispatcherIsRegistered(builder);
builder.Properties[DispatcherRegisteredKey] = true;
return builder.UseMiddleware<DispatcherMiddleware>();
}
@ -21,6 +25,14 @@ namespace Microsoft.AspNetCore.Builder
{
VerifyDispatcherIsRegistered(builder);
if (!builder.Properties.TryGetValue(DispatcherRegisteredKey, out _))
{
var message = $"{nameof(DispatcherMiddleware)} must be added to the request execution pipeline before {nameof(EndpointMiddleware)}. " +
$"Please add {nameof(DispatcherMiddleware)} by calling '{nameof(IApplicationBuilder)}.{nameof(UseDispatcher)}' inside the call to 'Configure(...)' in the application startup code.";
throw new InvalidOperationException(message);
}
return builder.UseMiddleware<EndpointMiddleware>();
}

View File

@ -34,7 +34,10 @@ namespace Microsoft.AspNetCore.Routing
var feature = httpContext.Features.Get<IEndpointFeature>();
if (feature == null)
{
throw new InvalidOperationException("Unable to execute an endpoint because the dispatcher was not run. Ensure dispatcher middleware is registered.");
var message = $"Unable to execute an endpoint because the {nameof(DispatcherMiddleware)} was not run for this request. " +
$"Ensure {nameof(DispatcherMiddleware)} is added to the request execution pipeline before {nameof(EndpointMiddleware)} in application startup code.";
throw new InvalidOperationException(message);
}
if (feature.Invoker != null)

View File

@ -9,18 +9,28 @@ namespace Microsoft.AspNetCore.Routing.Matchers
// to PathTokenizer.
internal static class FastPathTokenizer
{
// The default limit for the number of segments we tokenize.
//
// Historically the limit on the number of segments routing supports is 28.
// RoutePrecedence computes precedence based on a decimal, which supports 28
// or 29 digits.
//
// So setting this limit to 32 should work pretty well. We also expect the tokenizer
// to be used with stackalloc, so we want a small number.
public const int DefaultSegmentCount = 32;
// This section tokenizes the path by marking the sequence of slashes, and their
// and the length of the text between them.
//
// If there is residue (text after last slash) then the length of the segment will
// computed based on the string length.
public static unsafe int Tokenize(string path, PathSegment* segments, int maxCount)
public static int Tokenize(string path, Span<PathSegment> segments)
{
int count = 0;
int start = 1; // Paths always start with a leading /
int end;
var span = path.AsSpan(start);
while ((end = span.IndexOf('/')) >= 0 && count < maxCount)
while ((end = span.IndexOf('/')) >= 0 && count < segments.Length)
{
segments[count++] = new PathSegment(start, end);
start += end + 1; // resume search after the current character
@ -29,7 +39,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers
// Residue
var length = span.Length;
if (length > 0 && count < maxCount)
if (length > 0 && count < segments.Length)
{
segments[count++] = new PathSegment(start, length);
}

View File

@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers
_exitDestination = exitDestination;
}
public unsafe override int GetDestination(string path, PathSegment segment)
public override int GetDestination(string path, PathSegment segment)
{
return segment.Length == 0 ? _exitDestination : _defaultDestination;
}

View File

@ -12,7 +12,7 @@ using Xunit;
namespace Microsoft.AspNetCore.Builder
{
public class DispatcherApplicationBuilderExtensions
public class DispatcherApplicationBuilderExtensionsTest
{
[Fact]
public void UseDispatcher_ServicesNotRegistered_Throws()
@ -69,7 +69,26 @@ namespace Microsoft.AspNetCore.Builder
}
[Fact]
public async Task UseEndpoint_ServicesRegistered_SetsFeature()
public void UseEndpoint_ServicesRegisteredAndNoDispatcherRegistered_Throws()
{
// Arrange
var services = CreateServices();
var app = new ApplicationBuilder(services);
// Act
var ex = Assert.Throws<InvalidOperationException>(() => app.UseEndpoint());
// Assert
Assert.Equal(
"DispatcherMiddleware must be added to the request execution pipeline before EndpointMiddleware. " +
"Please add DispatcherMiddleware by calling 'IApplicationBuilder.UseDispatcher' " +
"inside the call to 'Configure(...)' in the application startup code.",
ex.Message);
}
[Fact]
public async Task UseEndpoint_ServicesRegisteredAndDispatcherRegistered_SetsFeature()
{
// Arrange
var services = CreateServices();

View File

@ -34,7 +34,10 @@ namespace Microsoft.AspNetCore.Routing
// Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () => await invokeTask);
Assert.Equal("Unable to execute an endpoint because the dispatcher was not run. Ensure dispatcher middleware is registered.", ex.Message);
Assert.Equal(
"Unable to execute an endpoint because the DispatcherMiddleware was not run for this request. " +
"Ensure DispatcherMiddleware is added to the request execution pipeline before EndpointMiddleware in application startup code.",
ex.Message);
}
private class ServiceProvider : IServiceProvider

View File

@ -12,11 +12,11 @@ namespace Microsoft.AspNetCore.Routing.Matchers
// to establish a lower bound for perf comparisons.
internal class BarebonesMatcher : Matcher
{
public readonly InnerMatcher[] _matchers;
public readonly InnerMatcher[] Matchers;
public BarebonesMatcher(InnerMatcher[] matchers)
{
_matchers = matchers;
Matchers = matchers;
}
public override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature)
@ -31,11 +31,11 @@ namespace Microsoft.AspNetCore.Routing.Matchers
throw new ArgumentNullException(nameof(feature));
}
for (var i = 0; i < _matchers.Length; i++)
for (var i = 0; i < Matchers.Length; i++)
{
if (_matchers[i].TryMatch(httpContext, feature))
if (Matchers[i].TryMatch(httpContext.Request.Path.Value))
{
feature.Endpoint = _matchers[i]._endpoint;
feature.Endpoint = Matchers[i].Endpoint;
feature.Values = new RouteValueDictionary();
}
}
@ -45,21 +45,27 @@ namespace Microsoft.AspNetCore.Routing.Matchers
public sealed class InnerMatcher : Matcher
{
public readonly MatcherEndpoint Endpoint;
private readonly string[] _segments;
public readonly MatcherEndpoint _endpoint;
private readonly CandidateSet _candidates;
public InnerMatcher(string[] segments, MatcherEndpoint endpoint)
{
_segments = segments;
_endpoint = endpoint;
Endpoint = endpoint;
_candidates = new CandidateSet(
new Candidate[] { new Candidate(endpoint), },
// Single candidate group that contains one entry.
CandidateSet.MakeGroups(new[] { 1 }));
}
public bool TryMatch(HttpContext httpContext, IEndpointFeature feature)
public bool TryMatch(string path)
{
var segment = 0;
var path = httpContext.Request.Path.Value;
var start = 1; // PathString always has a leading slash
var end = 0;
while ((end = path.IndexOf('/', start)) >= 0)
@ -67,7 +73,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers
var comparand = _segments.Length > segment ? _segments[segment] : null;
if ((comparand == null && end - start == 0) ||
(comparand != null &&
(comparand.Length != end - start ||
(comparand.Length != end - start ||
string.Compare(
path,
start,
@ -78,7 +84,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers
{
return false;
}
start = end + 1;
segment++;
}
@ -107,11 +113,21 @@ namespace Microsoft.AspNetCore.Routing.Matchers
return segment == _segments.Length;
}
internal CandidateSet SelectCandidates(string path, ReadOnlySpan<PathSegment> segments)
{
if (TryMatch(path))
{
return _candidates;
}
return CandidateSet.Empty;
}
public override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature)
{
if (TryMatch(httpContext, feature))
if (TryMatch(httpContext.Request.Path.Value))
{
feature.Endpoint = _endpoint;
feature.Endpoint = Endpoint;
feature.Values = new RouteValueDictionary();
}
@ -119,4 +135,4 @@ namespace Microsoft.AspNetCore.Routing.Matchers
}
}
}
}
}

View File

@ -0,0 +1,28 @@
// 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;
namespace Microsoft.AspNetCore.Routing.Matchers
{
// This is not yet fleshed out - consider this part of the
// work-in-progress definition of CandidateSet.
internal readonly struct Candidate
{
public readonly MatcherEndpoint Endpoint;
public readonly string[] Parameters;
public Candidate(MatcherEndpoint endpoint)
{
Endpoint = endpoint;
Parameters = Array.Empty<string>();
}
public Candidate(MatcherEndpoint endpoint, string[] parameters)
{
Endpoint = endpoint;
Parameters = parameters;
}
}
}

View File

@ -0,0 +1,59 @@
// 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;
namespace Microsoft.AspNetCore.Routing.Matchers
{
// This is not yet fleshed out - this is a work in progress to
// unblock the benchmarks.
internal class CandidateSet
{
public static readonly CandidateSet Empty = new CandidateSet(Array.Empty<Candidate>(), Array.Empty<int>());
// The array of candidates.
public readonly Candidate[] Candidates;
// The number of groups.
public readonly int GroupCount;
// The array of groups. Groups define a contiguous sets of indices into
// the candidates array.
//
// The groups array always contains N+1 entries where N is the number of groups.
// The extra array entry is there to make indexing easier, so we can lookup the 'end'
// of the last group without branching.
//
// Example:
// Group0: Candidates[0], Candidates[1]
// Group1: Candidates[2], Candidates[3], Candidates[4]
//
// The groups array would look like: { 0, 2, 5, }
public readonly int[] Groups;
public CandidateSet(Candidate[] candidates, int[] groups)
{
Candidates = candidates;
Groups = groups;
GroupCount = groups.Length == 0 ? 0 : groups.Length - 1;
}
// See description on Groups.
public static int[] MakeGroups(int[] lengths)
{
var groups = new int[lengths.Length + 1];
var sum = 0;
for (var i = 0; i < lengths.Length; i++)
{
groups[i] = sum;
sum += lengths[i];
}
groups[lengths.Length] = sum;
return groups;
}
}
}

View File

@ -3,8 +3,10 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing.EndpointConstraints;
namespace Microsoft.AspNetCore.Routing.Matchers
{
@ -17,7 +19,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers
_states = states;
}
public unsafe override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature)
public override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature)
{
if (httpContext == null)
{
@ -29,45 +31,52 @@ namespace Microsoft.AspNetCore.Routing.Matchers
throw new ArgumentNullException(nameof(feature));
}
var states = _states;
var current = 0;
var path = httpContext.Request.Path.Value;
var buffer = stackalloc PathSegment[32];
var count = FastPathTokenizer.Tokenize(path, buffer, 32);
for (var i = 0; i < count; i++)
{
current = states[current].Transitions.GetDestination(path, buffer[i]);
}
Span<PathSegment> segments = stackalloc PathSegment[FastPathTokenizer.DefaultSegmentCount];
var count = FastPathTokenizer.Tokenize(path, segments);
var candidates = SelectCandidates(path, segments.Slice(0, count));
var matches = new List<(Endpoint, RouteValueDictionary)>();
var candidates = states[current].Matches;
for (var i = 0; i < candidates.Length; i++)
// This code ignores groups for right now.
for (var i = 0; i < candidates.Candidates.Length; i++)
{
var isMatch = true;
var candidate = candidates.Candidates[i];
var values = new RouteValueDictionary();
var parameters = candidates[i].Parameters;
var parameters = candidate.Parameters;
if (parameters != null)
{
for (var j = 0; j < parameters.Length; j++)
{
var parameter = parameters[j];
if (parameter != null && buffer[j].Length == 0)
if (parameter != null && segments[j].Length == 0)
{
goto notmatch;
isMatch = false;
break;
}
else if (parameter != null)
{
var value = path.Substring(buffer[j].Start, buffer[j].Length);
var value = path.Substring(segments[j].Start, segments[j].Length);
values.Add(parameter, value);
}
}
}
matches.Add((candidates[i].Endpoint, values));
// This is some super super temporary code so we can pass the benchmarks
// that do HTTP method matching.
var httpMethodConstraint = candidate.Endpoint.Metadata.GetMetadata<HttpMethodEndpointConstraint>();
if (httpMethodConstraint != null && !MatchHttpMethod(httpContext.Request.Method, httpMethodConstraint))
{
isMatch = false;
}
notmatch: ;
if (isMatch)
{
matches.Add((candidate.Endpoint, values));
}
}
feature.Endpoint = matches.Count == 0 ? null : matches[0].Item1;
@ -76,17 +85,50 @@ namespace Microsoft.AspNetCore.Routing.Matchers
return Task.CompletedTask;
}
public struct State
// This is some super super temporary code so we can pass the benchmarks
// that do HTTP method matching.
private bool MatchHttpMethod(string httpMethod, HttpMethodEndpointConstraint constraint)
{
public bool IsAccepting;
public Candidate[] Matches;
public JumpTable Transitions;
foreach (var supportedHttpMethod in constraint.HttpMethods)
{
if (string.Equals(supportedHttpMethod, httpMethod, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
public struct Candidate
public CandidateSet SelectCandidates(string path, ReadOnlySpan<PathSegment> segments)
{
public Endpoint Endpoint;
public string[] Parameters;
var states = _states;
var current = 0;
for (var i = 0; i < segments.Length; i++)
{
current = states[current].Transitions.GetDestination(path, segments[i]);
}
return states[current].Candidates;
}
[DebuggerDisplay("{DebuggerToString(),nq}")]
public readonly struct State
{
public readonly CandidateSet Candidates;
public readonly JumpTable Transitions;
public State(CandidateSet candidates, JumpTable transitions)
{
Candidates = candidates;
Transitions = transitions;
}
public string DebuggerToString()
{
return $"m: {Candidates.Candidates?.Length ?? 0}, j: ({Transitions?.DebuggerToString()})";
}
}
}
}

View File

@ -13,23 +13,17 @@ namespace Microsoft.AspNetCore.Routing.Matchers
{
internal class DfaMatcherBuilder : MatcherBuilder
{
private List<Entry> _entries = new List<Entry>();
private List<MatcherBuilderEntry> _entries = new List<MatcherBuilderEntry>();
public override void AddEndpoint(MatcherEndpoint endpoint)
{
var parsed = TemplateParser.Parse(endpoint.Template);
_entries.Add(new Entry()
{
Order = 0,
Pattern = parsed,
Precedence = RoutePrecedence.ComputeInbound(parsed),
Endpoint = endpoint,
});
_entries.Add(new MatcherBuilderEntry(endpoint));
}
public override Matcher Build()
{
Sort(_entries);
_entries.Sort();
var root = new Node() { Depth = -1 };
@ -108,7 +102,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers
AddNode(root, states, tables);
var exit = states.Count;
states.Add(new State() { IsAccepting = false, Matches = Array.Empty<Candidate>(), });
states.Add(new State(CandidateSet.Empty, null));
tables.Add(new JumpTableBuilder() { DefaultDestination = exit, ExitDestination = exit, });
for (var i = 0; i < tables.Count; i++)
@ -126,12 +120,7 @@ namespace Microsoft.AspNetCore.Routing.Matchers
for (var i = 0; i < states.Count; i++)
{
states[i] = new State()
{
IsAccepting = states[i].IsAccepting,
Matches = states[i].Matches,
Transitions = tables[i].Build(),
};
states[i] = new State(states[i].Candidates, tables[i].Build());
}
return new DfaMatcher(states.ToArray());
@ -154,14 +143,18 @@ namespace Microsoft.AspNetCore.Routing.Matchers
private static int AddNode(Node node, List<State> states, List<JumpTableBuilder> tables)
{
Sort(node.Matches);
node.Matches.Sort();
var index = states.Count;
states.Add(new State()
{
Matches = node.Matches.Select(CreateCandidate).ToArray(),
IsAccepting = node.Matches.Count > 0,
});
// This is just temporary. This code ignores groups for now, and creates
// a single group with all matches.
var candidates = new CandidateSet(
node.Matches.Select(CreateCandidate).ToArray(),
CandidateSet.MakeGroups(new int[] { node.Matches.Count, }));
// JumpTable temporarily null. Will be patched later.
states.Add(new State(candidates, null));
var table = new JumpTableBuilder();
tables.Add(table);
@ -187,33 +180,12 @@ namespace Microsoft.AspNetCore.Routing.Matchers
return index;
}
private static Candidate CreateCandidate(Entry entry)
private static Candidate CreateCandidate(MatcherBuilderEntry entry)
{
return new Candidate()
{
Endpoint = entry.Endpoint,
Parameters = entry.Pattern.Segments.Select(s => s.IsSimple && s.Parts[0].IsParameter ? s.Parts[0].Name : null).ToArray(),
};
}
private static void Sort(List<Entry> entries)
{
entries.Sort((x, y) =>
{
var comparison = x.Order.CompareTo(y.Order);
if (comparison != 0)
{
return comparison;
}
comparison = x.Precedence.CompareTo(y.Precedence);
if (comparison != 0)
{
return comparison;
}
return x.Pattern.TemplateText.CompareTo(y.Pattern.TemplateText);
});
var parameters = entry.Pattern.Segments
.Select(s => s.IsSimple && s.Parts[0].IsParameter ? s.Parts[0].Name : null)
.ToArray();
return new Candidate(entry.Endpoint, parameters);
}
private static Node DeepCopy(Node node)
@ -229,20 +201,12 @@ namespace Microsoft.AspNetCore.Routing.Matchers
return node;
}
private class Entry
{
public int Order;
public decimal Precedence;
public RouteTemplate Pattern;
public Endpoint Endpoint;
}
[DebuggerDisplay("{DebuggerToString(),nq}")]
private class Node
{
public int Depth { get; set; }
public List<Entry> Matches { get; } = new List<Entry>();
public List<MatcherBuilderEntry> Matches { get; } = new List<MatcherBuilderEntry>();
public Dictionary<string, Node> Literals { get; } = new Dictionary<string, Node>(StringComparer.OrdinalIgnoreCase);

View File

@ -1,20 +1,21 @@
// 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 Xunit;
namespace Microsoft.AspNetCore.Routing.Matchers
{
public unsafe class FastPathTokenizerTest
public class FastPathTokenizerTest
{
[Fact] // Note: tokenizing a truly empty string is undefined.
public void Tokenize_EmptyPath()
{
// Arrange
var segments = stackalloc PathSegment[32];
Span<PathSegment> segments = stackalloc PathSegment[1];
// Act
var count = FastPathTokenizer.Tokenize("/", segments, 1);
var count = FastPathTokenizer.Tokenize("/", segments);
// Assert
Assert.Equal(0, count);
@ -24,10 +25,10 @@ namespace Microsoft.AspNetCore.Routing.Matchers
public void Tokenize_SingleSegment()
{
// Arrange
var segments = stackalloc PathSegment[32];
Span<PathSegment> segments = stackalloc PathSegment[1];
// Act
var count = FastPathTokenizer.Tokenize("/abc", segments, 1);
var count = FastPathTokenizer.Tokenize("/abc", segments);
// Assert
Assert.Equal(1, count);
@ -38,10 +39,10 @@ namespace Microsoft.AspNetCore.Routing.Matchers
public void Tokenize_WithSomeSegments()
{
// Arrange
var segments = stackalloc PathSegment[32];
Span<PathSegment> segments = stackalloc PathSegment[3];
// Act
var count = FastPathTokenizer.Tokenize("/a/b/c", segments, 3);
var count = FastPathTokenizer.Tokenize("/a/b/c", segments);
// Assert
Assert.Equal(3, count);
@ -54,10 +55,10 @@ namespace Microsoft.AspNetCore.Routing.Matchers
public void Tokenize_WithSomeSegments_TrailingSlash()
{
// Arrange
var segments = stackalloc PathSegment[32];
Span<PathSegment> segments = stackalloc PathSegment[3];
// Act
var count = FastPathTokenizer.Tokenize("/a/b/c/", segments, 3);
var count = FastPathTokenizer.Tokenize("/a/b/c/", segments);
// Assert
Assert.Equal(3, count);
@ -70,10 +71,10 @@ namespace Microsoft.AspNetCore.Routing.Matchers
public void Tokenize_LongerSegments()
{
// Arrange
var segments = stackalloc PathSegment[32];
Span<PathSegment> segments = stackalloc PathSegment[3];
// Act
var count = FastPathTokenizer.Tokenize("/aaa/bb/ccccc", segments, 3);
var count = FastPathTokenizer.Tokenize("/aaa/bb/ccccc", segments);
// Assert
Assert.Equal(3, count);
@ -86,10 +87,10 @@ namespace Microsoft.AspNetCore.Routing.Matchers
public void Tokenize_EmptySegments()
{
// Arrange
var segments = stackalloc PathSegment[32];
Span<PathSegment> segments = stackalloc PathSegment[3];
// Act
var count = FastPathTokenizer.Tokenize("///c", segments, 3);
var count = FastPathTokenizer.Tokenize("///c", segments);
// Assert
Assert.Equal(3, count);
@ -102,10 +103,10 @@ namespace Microsoft.AspNetCore.Routing.Matchers
public void Tokenize_TooManySegments()
{
// Arrange
var segments = stackalloc PathSegment[32];
Span<PathSegment> segments = stackalloc PathSegment[3];
// Act
var count = FastPathTokenizer.Tokenize("/a/b/c/d", segments, 3);
var count = FastPathTokenizer.Tokenize("/a/b/c/d", segments);
// Assert
Assert.Equal(3, count);

View File

@ -0,0 +1,58 @@
// 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.Linq;
using Microsoft.AspNetCore.Routing.EndpointConstraints;
using Microsoft.AspNetCore.Routing.Template;
namespace Microsoft.AspNetCore.Routing.Matchers
{
internal class MatcherBuilderEntry : IComparable<MatcherBuilderEntry>
{
public MatcherBuilderEntry(MatcherEndpoint endpoint)
{
Endpoint = endpoint;
HttpMethod = endpoint.Metadata
.OfType<HttpMethodEndpointConstraint>()
.FirstOrDefault()?.HttpMethods.Single();
Precedence = RoutePrecedence.ComputeInbound(endpoint.ParsedTemplate);
}
public MatcherEndpoint Endpoint { get; }
public string HttpMethod { get; }
public int Order => Endpoint.Order;
public RouteTemplate Pattern => Endpoint.ParsedTemplate;
public decimal Precedence { get; }
public int CompareTo(MatcherBuilderEntry other)
{
var comparison = Order.CompareTo(other.Order);
if (comparison != 0)
{
return comparison;
}
comparison = Precedence.CompareTo(other.Precedence);
if (comparison != 0)
{
return comparison;
}
// Treat the presence of an HttpMethod as a boolean for the purposes of
// comparison. We want HttpMethod != null to mean *more specific*.
comparison = (HttpMethod == null).CompareTo(other.HttpMethod == null);
if (comparison != 0)
{
return comparison;
}
return Pattern.TemplateText.CompareTo(other.Pattern.TemplateText);
}
}
}

View File

@ -3,8 +3,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Routing.EndpointConstraints;
using Microsoft.AspNetCore.Routing.Template;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Routing.Matchers
@ -12,80 +15,90 @@ namespace Microsoft.AspNetCore.Routing.Matchers
internal class RouteMatcherBuilder : MatcherBuilder
{
private readonly IInlineConstraintResolver _constraintResolver;
private readonly List<Entry> _entries;
private readonly List<MatcherBuilderEntry> _entries;
public RouteMatcherBuilder()
{
_constraintResolver = new DefaultInlineConstraintResolver(Options.Create(new RouteOptions()));
_entries = new List<Entry>();
_entries = new List<MatcherBuilderEntry>();
}
public override void AddEndpoint(MatcherEndpoint endpoint)
{
var handler = new RouteHandler(c =>
{
c.Features.Get<IEndpointFeature>().Endpoint = endpoint;
return Task.CompletedTask;
});
// MatcherEndpoint.Values contains the default values parsed from the template
// as well as those specified with a literal. We need to separate those
// for legacy cases.
var defaults = endpoint.Defaults;
for (var i = 0; i < endpoint.ParsedTemplate.Parameters.Count; i++)
{
var parameter = endpoint.ParsedTemplate.Parameters[i];
if (parameter.DefaultValue != null)
{
defaults.Remove(parameter.Name);
}
}
_entries.Add(new Entry()
{
Endpoint = endpoint,
Route = new Route(
handler,
endpoint.Template,
defaults,
new Dictionary<string, object>(),
new RouteValueDictionary(),
_constraintResolver),
});
_entries.Add(new MatcherBuilderEntry(endpoint));
}
public override Matcher Build()
{
_entries.Sort();
var cache = new EndpointConstraintCache(
new CompositeEndpointDataSource(Array.Empty<EndpointDataSource>()),
new[] { new DefaultEndpointConstraintProvider(), });
var selector = new EndpointSelector(null, cache, NullLoggerFactory.Instance);
var groups = _entries
.GroupBy(e => (e.Order, e.Precedence, e.Endpoint.Template))
.OrderBy(g => g.Key.Order)
.ThenBy(g => g.Key.Precedence);
var routes = new RouteCollection();
for (var i = 0; i < _entries.Count; i++)
foreach (var group in groups)
{
routes.Add(_entries[i].Route);
var candidates = group.Select(e => e.Endpoint).ToArray();
// MatcherEndpoint.Values contains the default values parsed from the template
// as well as those specified with a literal. We need to separate those
// for legacy cases.
var endpoint = group.First().Endpoint;
var defaults = new RouteValueDictionary(endpoint.Defaults);
for (var i = 0; i < endpoint.ParsedTemplate.Parameters.Count; i++)
{
var parameter = endpoint.ParsedTemplate.Parameters[i];
if (parameter.DefaultValue != null)
{
defaults.Remove(parameter.Name);
}
}
routes.Add(new Route(
new SelectorRouter(selector, candidates),
endpoint.Template,
defaults,
new Dictionary<string, object>(),
new RouteValueDictionary(),
_constraintResolver));
}
return new RouteMatcher(routes);
}
private struct Entry : IComparable<Entry>
private class SelectorRouter : IRouter
{
public MatcherEndpoint Endpoint;
public Route Route;
private readonly EndpointSelector _selector;
private readonly Endpoint[] _candidates;
public int CompareTo(Entry other)
public SelectorRouter(EndpointSelector selector, Endpoint[] candidates)
{
var comparison = Endpoint.Order.CompareTo(other.Endpoint.Order);
if (comparison != 0)
{
return comparison;
}
_selector = selector;
_candidates = candidates;
}
comparison = RoutePrecedence.ComputeInbound(Endpoint.ParsedTemplate).CompareTo(RoutePrecedence.ComputeInbound(other.Endpoint.ParsedTemplate));
if (comparison != 0)
{
return comparison;
}
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
throw new NotImplementedException();
}
return Endpoint.Template.CompareTo(other.Endpoint.Template);
public Task RouteAsync(RouteContext context)
{
var endpoint = _selector.SelectBestCandidate(context.HttpContext, _candidates);
if (endpoint != null)
{
context.HttpContext.Features.Get<IEndpointFeature>().Endpoint = endpoint;
context.Handler = (_) => Task.CompletedTask;
}
return Task.CompletedTask;
}
}
}

View File

@ -2,8 +2,12 @@
// 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.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Routing.EndpointConstraints;
using Microsoft.AspNetCore.Routing.Internal;
using Microsoft.AspNetCore.Routing.Template;
using Microsoft.AspNetCore.Routing.Tree;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.ObjectPool;
@ -13,51 +17,93 @@ namespace Microsoft.AspNetCore.Routing.Matchers
{
internal class TreeRouterMatcherBuilder : MatcherBuilder
{
private readonly TreeRouteBuilder _inner;
private readonly List<MatcherBuilderEntry> _entries;
public TreeRouterMatcherBuilder()
{
_inner = new TreeRouteBuilder(
NullLoggerFactory.Instance,
new DefaultObjectPool<UriBuildingContext>(new UriBuilderContextPooledObjectPolicy()),
new DefaultInlineConstraintResolver(Options.Create(new RouteOptions())));
_entries = new List<MatcherBuilderEntry>();
}
public override void AddEndpoint(MatcherEndpoint endpoint)
{
var handler = new RouteHandler(c =>
{
var feature = c.Features.Get<IEndpointFeature>();
feature.Endpoint = endpoint;
feature.Invoker = MatcherEndpoint.EmptyInvoker;
return Task.CompletedTask;
});
// MatcherEndpoint.Values contains the default values parsed from the template
// as well as those specified with a literal. We need to separate those
// for legacy cases.
var defaults = endpoint.Defaults;
for (var i = 0; i < endpoint.ParsedTemplate.Parameters.Count; i++)
{
var parameter = endpoint.ParsedTemplate.Parameters[i];
if (parameter.DefaultValue == null && defaults.ContainsKey(parameter.Name))
{
throw new InvalidOperationException(
"The TreeRouter does not support non-inline default values.");
}
}
_inner.MapInbound(
handler,
endpoint.ParsedTemplate,
routeName: null,
order: endpoint.Order);
_entries.Add(new MatcherBuilderEntry(endpoint));
}
public override Matcher Build()
{
return new TreeRouterMatcher(_inner.Build());
_entries.Sort();
var builder = new TreeRouteBuilder(
NullLoggerFactory.Instance,
new DefaultObjectPool<UriBuildingContext>(new UriBuilderContextPooledObjectPolicy()),
new DefaultInlineConstraintResolver(Options.Create(new RouteOptions())));
var cache = new EndpointConstraintCache(
new CompositeEndpointDataSource(Array.Empty<EndpointDataSource>()),
new[] { new DefaultEndpointConstraintProvider(), });
var selector = new EndpointSelector(null, cache, NullLoggerFactory.Instance);
var groups = _entries
.GroupBy(e => (e.Order, e.Precedence, e.Endpoint.Template))
.OrderBy(g => g.Key.Order)
.ThenBy(g => g.Key.Precedence);
var routes = new RouteCollection();
foreach (var group in groups)
{
var candidates = group.Select(e => e.Endpoint).ToArray();
// MatcherEndpoint.Values contains the default values parsed from the template
// as well as those specified with a literal. We need to separate those
// for legacy cases.
var endpoint = group.First().Endpoint;
var defaults = new RouteValueDictionary(endpoint.Defaults);
for (var i = 0; i < endpoint.ParsedTemplate.Parameters.Count; i++)
{
var parameter = endpoint.ParsedTemplate.Parameters[i];
if (parameter.DefaultValue != null)
{
defaults.Remove(parameter.Name);
}
}
builder.MapInbound(
new SelectorRouter(selector, candidates),
endpoint.ParsedTemplate,
routeName: null,
order: endpoint.Order);
}
return new TreeRouterMatcher(builder.Build());
}
private class SelectorRouter : IRouter
{
private readonly EndpointSelector _selector;
private readonly Endpoint[] _candidates;
public SelectorRouter(EndpointSelector selector, Endpoint[] candidates)
{
_selector = selector;
_candidates = candidates;
}
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
throw new NotImplementedException();
}
public Task RouteAsync(RouteContext context)
{
var endpoint = _selector.SelectBestCandidate(context.HttpContext, _candidates);
if (endpoint != null)
{
context.HttpContext.Features.Get<IEndpointFeature>().Endpoint = endpoint;
context.Handler = (_) => Task.CompletedTask;
}
return Task.CompletedTask;
}
}
}
}