123 lines
4.1 KiB
C#
123 lines
4.1 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
namespace Microsoft.AspNetCore.Routing.Matchers
|
|
{
|
|
// A test-only matcher implementation - used as a baseline for more compilated
|
|
// 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 BarebonesMatcher : Matcher
|
|
{
|
|
public readonly InnerMatcher[] _matchers;
|
|
|
|
public BarebonesMatcher(InnerMatcher[] matchers)
|
|
{
|
|
_matchers = matchers;
|
|
}
|
|
|
|
public override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature)
|
|
{
|
|
if (httpContext == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(httpContext));
|
|
}
|
|
|
|
if (feature == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(feature));
|
|
}
|
|
|
|
for (var i = 0; i < _matchers.Length; i++)
|
|
{
|
|
if (_matchers[i].TryMatch(httpContext, feature))
|
|
{
|
|
feature.Endpoint = _matchers[i]._endpoint;
|
|
feature.Values = new RouteValueDictionary();
|
|
}
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public sealed class InnerMatcher : Matcher
|
|
{
|
|
private readonly string[] _segments;
|
|
public readonly MatcherEndpoint _endpoint;
|
|
|
|
public InnerMatcher(string[] segments, MatcherEndpoint endpoint)
|
|
{
|
|
_segments = segments;
|
|
_endpoint = endpoint;
|
|
}
|
|
|
|
public bool TryMatch(HttpContext httpContext, IEndpointFeature feature)
|
|
{
|
|
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)
|
|
{
|
|
var comparand = _segments.Length > segment ? _segments[segment] : null;
|
|
if ((comparand == null && end - start == 0) ||
|
|
(comparand != null &&
|
|
(comparand.Length != end - start ||
|
|
string.Compare(
|
|
path,
|
|
start,
|
|
comparand,
|
|
0,
|
|
comparand.Length,
|
|
StringComparison.OrdinalIgnoreCase) != 0)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
start = end + 1;
|
|
segment++;
|
|
}
|
|
|
|
// residue
|
|
var length = path.Length - start;
|
|
if (length > 0)
|
|
{
|
|
var comparand = _segments.Length > segment ? _segments[segment] : null;
|
|
if (comparand != null &&
|
|
(comparand.Length != length ||
|
|
string.Compare(
|
|
path,
|
|
start,
|
|
comparand,
|
|
0,
|
|
comparand.Length,
|
|
StringComparison.OrdinalIgnoreCase) != 0))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
segment++;
|
|
}
|
|
|
|
return segment == _segments.Length;
|
|
}
|
|
|
|
public override Task MatchAsync(HttpContext httpContext, IEndpointFeature feature)
|
|
{
|
|
if (TryMatch(httpContext, feature))
|
|
{
|
|
feature.Endpoint = _endpoint;
|
|
feature.Values = new RouteValueDictionary();
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|
|
}
|
|
}
|