< Summary

Information
Class: NanoRoute.Router
Assembly: NanoRoute.dll
File(s): /home/runner/work/nanoroute/nanoroute/Src/NanoRoute/Public/Router.cs
Line coverage
100%
Covered lines: 14
Uncovered lines: 0
Coverable lines: 14
Total lines: 109
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBlocks covered Blocks not covered
CopyRoot(...)40
Router(...)60

File(s)

/home/runner/work/nanoroute/nanoroute/Src/NanoRoute/Public/Router.cs

#LineLine coverage
 1/********************************************************************************
 2* Router.cs                                                                     *
 3*                                                                               *
 4* Author: Denes Solti                                                           *
 5********************************************************************************/
 6using System;
 7using System.Diagnostics.CodeAnalysis;
 8using System.Net.Http;
 9using System.Threading;
 10using System.Threading.Tasks;
 11
 12namespace NanoRoute
 13{
 14    using Internals;
 15
 16    /// <summary>
 17    /// Executes the route matching pipeline built by <see cref="RouteBuilder"/>.
 18    /// </summary>
 19    /// <remarks>
 20    /// A router is created from a builder snapshot. Matching walks the configured route tree, attaches bound parameters
 21    /// handlers in order until one returns a response without delegating further.
 22    /// </remarks>
 23    public abstract class Router: RoutingContext
 24    {
 25        /// <summary>
 26        /// The request property key that stores the trace identifier associated with the current request.
 27        /// </summary>
 28        public const string TraceIdName = "TraceId";
 29
 30        /// <summary>
 31        /// The request property key that stores the original transport-specific request object.
 32        /// </summary>
 33        public const string OriginalRequestName = "OriginalRequest";
 34
 35        private static RouteNode CopyRoot(RouteBuilder routeBuilder)
 236        {
 37            // The base() ctor invocation runs first so we have to do the validation here
 238            Ensure.NotNull(routeBuilder);
 239            return routeBuilder.GetRoot(frozen: true);
 240        }
 41
 42        /// <summary>
 43        /// Initializes a router from a route builder snapshot and router configuration.
 44        /// </summary>
 45        /// <param name="routeBuilder">The builder whose current route tree should be frozen into this router.</param>
 46        /// <param name="config">The router configuration that controls runtime behavior.</param>
 47        [SuppressMessage("ApiDesign", "RS0022:Constructor make noninheritable base class inheritable")]
 248        protected Router(RouteBuilder routeBuilder, RouterConfig config): base(CopyRoot(routeBuilder))
 249        {
 50            //Ensure.NotNull(routeBuilder);
 251            Ensure.NotNull(config);
 52
 253            MatchingPrecedence = config.MatchingPrecedence;
 254        }
 55
 56        /// <summary>
 57        /// Gets the configured precedence between literal and parameterized child segments.
 58        /// </summary>
 59        public MatchingPrecedence MatchingPrecedence
 60        {
 61            get;
 62            private init
 263            {
 264                if (!Enum.IsDefined(typeof(MatchingPrecedence), value))
 165                    throw new ArgumentOutOfRangeException(nameof(value));
 66
 267                field = value;
 268            }
 69        }
 70
 71        /// <summary>
 72        /// Routes an <see cref="HttpRequestMessage"/> through the configured handler pipeline.
 73        /// </summary>
 74        /// <param name="request">The request to process.</param>
 75        /// <param name="services">The service provider exposed to value parsers and handlers.</param>
 76        /// <param name="cancellation">A token that can cancel request processing.</param>
 77        /// <returns>The <see cref="HttpResponseMessage"/> produced by the matching handlers.</returns>
 78        /// <remarks>
 79        /// Prefix routes can participate in the same pipeline as exact routes. Consecutive <c>/</c> separators in the
 80        /// request path are treated as a single separator during matching. When several handlers match, NanoRoute
 81        /// evaluates compatible matches from shorter prefixes toward more specific matches and honors
 82        /// <see cref="MatchingPrecedence"/> when both literal and parameterized segments are available at the same dept
 83        /// Once a branch is selected at a given depth, NanoRoute does not return to sibling branches later in the pipel
 84        /// </remarks>
 85        /// <exception cref="HttpRequestException">Thrown when no handler matches the request path.</exception>
 86        /// <exception cref="ArgumentException">Thrown when the request uses an unsupported HTTP method.</exception>
 87        /// <exception cref="OperationCanceledException">
 88        /// Thrown when the caller cancels the <paramref name="cancellation"/>.
 89        /// </exception>
 90        #if DEBUG
 91        internal
 92        #endif
 93        protected async Task<HttpResponseMessage> Handle(HttpRequestMessage request, IServiceProvider services, Cancella
 94        {
 95            Ensure.NotNull(request);
 96            Ensure.NotNull(services);
 97
 98            RouterEventSource.Info.Write("RequestProcessingStarted", static request => new
 99            {
 100                RequestUri = request.RequestUri.OriginalString,
 101                Verb = request.Method.Method
 102            }, request);
 103
 104            await using RequestPipeline pipeline = new(_root, MatchingPrecedence, request, services, cancellation);
 105
 106            return await pipeline.RunAsync();
 107        }
 108    }
 109}