< Summary

Information
Class: NanoRoute.RouterBuilder
Assembly: NanoRoute.dll
File(s): /home/runner/work/nanoroute/nanoroute/Src/NanoRoute/Public/RouterBuilder.cs
Line coverage
100%
Covered lines: 32
Uncovered lines: 0
Coverable lines: 32
Total lines: 171
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

File(s)

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

#LineLine coverage
 1/********************************************************************************
 2* RouterBuilder.cs                                                              *
 3*                                                                               *
 4* Author: Denes Solti                                                           *
 5********************************************************************************/
 6using System;
 7using System.Collections.Generic;
 8
 9namespace NanoRoute
 10{
 11    using Internals;
 12
 13    /// <summary>
 14    /// Builds a concrete <see cref="Router"/> type together with its strongly typed configuration object.
 15    /// </summary>
 16    /// <typeparam name="TRouter">The router type produced by <see cref="CreateRouter"/>.</typeparam>
 17    /// <typeparam name="TConfig">The configuration type exposed by <see cref="RouterConfig"/>.</typeparam>
 18    public sealed class RouterBuilder<TRouter, TConfig> : RouteBuilder where TRouter : Router where TConfig: RouterConfi
 19    {
 20        private readonly Func<RouterBuilder<TRouter, TConfig>, TRouter> _routerFactory;
 21
 22        /// <summary>
 23        /// Creates a builder that can produce <typeparamref name="TRouter"/> instances.
 24        /// </summary>
 25        /// <param name="routerFactory">
 26        /// A factory that receives this builder and returns a router backed by its current route snapshot.
 27        /// </param>
 228        public RouterBuilder(Func<RouterBuilder<TRouter, TConfig>, TRouter> routerFactory): base()
 229        {
 230            Ensure.NotNull(routerFactory);
 31
 232            _routerFactory = routerFactory;
 233        }
 34
 35        /// <summary>
 36        /// Registers a parser that can convert a route segment into a typed value and bind parser arguments once during
 37        /// </summary>
 38        /// <param name="parserName">The name used in route patterns such as <c>{id:int(min=1)}</c>.</param>
 39        /// <param name="bindArguments">Converts raw parser arguments into typed values once per route-template branch.<
 40        /// <param name="tryParseDelegate">The delegate that validates and parses a single path segment.</param>
 41        /// <returns>The current <see cref="RouterBuilder{TRouter, TConfig}"/> instance.</returns>
 42        public new RouterBuilder<TRouter, TConfig> AddValueParser(string parserName, BindArgumentsDelegate bindArguments
 143        {
 144            base.AddValueParser(parserName, bindArguments, tryParseDelegate);
 145            return this;
 146        }
 47
 48        /// <summary>
 49        /// Registers a handler for all supported HTTP methods.
 50        /// </summary>
 51        /// <param name="pattern">
 52        /// The route pattern to match. Literal segments are matched case-insensitively, parameter segments use
 53        /// registered parsers in the form <c>{parameterName:parserName}</c>, and a trailing <c>/</c> turns the
 54        /// pattern into a prefix match. Without a trailing slash, the pattern matches only the exact path.
 55        /// </param>
 56        /// <param name="handler">The handler to execute when the pattern matches.</param>
 57        /// <returns>The current <see cref="RouterBuilder{TRouter, TConfig}"/> instance.</returns>
 58        /// <example>
 59        /// <code>
 60        /// builder.AddHandler("/health", (context, next) =&gt; Results.Ok());
 61        /// </code>
 62        /// </example>
 63        public new RouterBuilder<TRouter, TConfig> AddHandler(string pattern, RequestHandlerDelegate handler)
 164        {
 165            base.AddHandler(pattern, handler);
 166            return this;
 167        }
 68
 69        /// <summary>
 70        /// Registers the same handler for multiple HTTP methods.
 71        /// </summary>
 72        /// <param name="verbs">The HTTP methods that should use the handler.</param>
 73        /// <param name="pattern">
 74        /// The route pattern to match. Literal segments are matched case-insensitively, parameter segments use
 75        /// registered parsers in the form <c>{parameterName:parserName}</c>, and a trailing <c>/</c> turns the
 76        /// pattern into a prefix match. Without a trailing slash, the pattern matches only the exact path.
 77        /// </param>
 78        /// <param name="handler">The handler to execute when the route matches.</param>
 79        /// <returns>The current <see cref="RouterBuilder{TRouter, TConfig}"/> instance.</returns>
 80        /// <exception cref="ArgumentException">Thrown when some of the <paramref name="verbs"/> represent a not support
 81        /// <exception cref="InvalidOperationException">Thrown when the <paramref name="pattern"/> references a value pa
 82        /// <example>
 83        /// <code>
 84        /// builder.AddHandler(
 85        ///     ["GET", "POST"],
 86        ///     "/api/items/{id:int}",
 87        ///     (context, next) =&gt; Results.Ok(context.Parameters["id"]));
 88        /// </code>
 89        /// </example>
 90        public new RouterBuilder<TRouter, TConfig> AddHandler(IEnumerable<string> verbs, string pattern, RequestHandlerD
 191        {
 192            base.AddHandler(verbs, pattern, handler);
 193            return this;
 194        }
 95
 96        /// <summary>
 97        /// Registers a handler for a single HTTP method.
 98        /// </summary>
 99        /// <param name="verb">The HTTP method that activates the handler.</param>
 100        /// <param name="pattern">
 101        /// The route pattern to match. Literal segments are matched case-insensitively, parameter segments use
 102        /// registered parsers in the form <c>{parameterName:parserName}</c>, and a trailing <c>/</c> turns the
 103        /// pattern into a prefix match. Without a trailing slash, the pattern matches only the exact path.
 104        /// </param>
 105        /// <param name="handler">
 106        /// The handler to execute. If several handlers match, calling the supplied <c>next</c> delegate continues
 107        /// the pipeline with the next compatible handler from the already selected route branch.
 108        /// </param>
 109        /// <returns>The current router instance.</returns>
 110        /// <exception cref="ArgumentException">Thrown when <paramref name="verb"/> is not a supported HTTP method.</exc
 111        /// <exception cref="InvalidOperationException">Thrown when the <paramref name="pattern"/> references a value pa
 112        /// <example>
 113        /// <code>
 114        /// builder.AddHandler("GET", "/files/{path:any}/", (context, next) =&gt;
 115        /// {
 116        ///     string path = (string) context.Parameters["path"]!;
 117        ///     return ServeFile(path);
 118        /// });
 119        /// </code>
 120        /// </example>
 121        public new RouterBuilder<TRouter, TConfig> AddHandler(string verb, string pattern, RequestHandlerDelegate handle
 2122        {
 2123            base.AddHandler(verb, pattern, handler);
 2124            return this;
 2125        }
 126
 127        /// <summary>
 128        /// Creates a scoped child builder under the given base prefix, invokes a configuration callback, and returns th
 129        /// </summary>
 130        /// <param name="pattern">The base prefix that child routes will be registered under.</param>
 131        /// <param name="configureRoutes">A callback that configures routes on the child builder.</param>
 132        /// <returns>The current builder.</returns>
 133        /// <exception cref="ArgumentException">Thrown when <paramref name="pattern"/> is not a valid route <paramref na
 134        /// <exception cref="InvalidOperationException">Thrown when the <paramref name="pattern"/> references a value pa
 135        public new RouterBuilder<TRouter, TConfig> AddPrefix(string pattern, Action<RouteBuilder> configureRoutes)
 1136        {
 1137            base.AddPrefix(pattern, configureRoutes);
 1138            return this;
 1139        }
 140
 141        /// <summary>
 142        /// Updates the router configuration object that will be used by future router instances.
 143        /// </summary>
 144        /// <param name="updateConfig">A callback that mutates <see cref="RouterConfig"/>.</param>
 145        /// <returns>The current builder.</returns>
 146        public RouterBuilder<TRouter, TConfig> WithConfiguration(Action<TConfig> updateConfig)
 1147        {
 1148            Ensure.NotNull(updateConfig);
 149
 1150            updateConfig(RouterConfig);
 151
 1152            return this;
 1153        }
 154
 155        /// <summary>
 156        /// Gets the mutable configuration object applied when <see cref="CreateRouter"/> is called.
 157        /// </summary>
 2158        public TConfig RouterConfig { get; } = new();
 159
 160        /// <summary>
 161        /// Creates a router from the builder's current routes, parser registrations, and configuration.
 162        /// </summary>
 163        /// <returns>A new <typeparamref name="TRouter"/> instance.</returns>
 164        /// <remarks>
 165        /// The created router is an immutable snapshot. Later changes to the builder or its configuration do not
 166        /// affect routers that have already been created.
 167        /// </remarks>
 2168        public TRouter CreateRouter() => _routerFactory(this);
 169    }
 170}
 171