< Summary

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

#LineLine coverage
 1/********************************************************************************
 2* NanoRouteQueryExtensions.cs                                                   *
 3*                                                                               *
 4* Author: Denes Solti                                                           *
 5********************************************************************************/
 6using System;
 7using System.Collections.Generic;
 8using System.Collections.Frozen;
 9
 10namespace NanoRoute
 11{
 12    using Internals;
 13    using Properties;
 14
 15    /// <summary>
 16    /// Adds query-parameter binding helpers to NanoRoute.
 17    /// </summary>
 18    public static class NanoRouteQueryExtensions
 19    {
 20        extension<TBuilder>(TBuilder routeBuilder) where TBuilder : RouteBuilder
 21        {
 22            /// <summary>
 23            /// Parses configured query parameters and stores their values in <see cref="RequestContext.Parameters"/>.
 24            /// </summary>
 25            /// <param name="bindings">
 26            /// A query-parameter descriptor such as <c>{filter:str(min=3)}&amp;{page?:int(min=1)}</c>.
 27            /// </param>
 28            /// <returns>The current <paramref name="routeBuilder"/> instance.</returns>
 29            /// <remarks>
 30            /// Parsed query values are written into <see cref="RequestContext.Parameters"/>. If that dictionary
 31            /// already contains the same key because of route binding, JSON binding, or earlier middleware, the
 32            /// query binding overwrites the existing value.
 33            /// </remarks>
 34            public TBuilder AddQueryBindings(string bindings)
 135            {
 136                Ensure.NotNull(routeBuilder);
 137                Ensure.NotNull(bindings);
 38
 139                return routeBuilder.AddQueryBindings
 140                (
 141                    Enum.GetNames(typeof(HttpVerb)),
 142                    "/",
 143                    bindings
 144                );
 45            }
 46
 47            /// <summary>
 48            /// Parses configured query parameters and stores their values in <see cref="RequestContext.Parameters"/>.
 49            /// </summary>
 50            /// <param name="verbs">The HTTP methods that activate the query-binding middleware.</param>
 51            /// <param name="bindings">
 52            /// A query-parameter descriptor such as <c>{filter:str(min=3)}&amp;{page?:int(min=1)}</c>.
 53            /// </param>
 54            /// <returns>The current <paramref name="routeBuilder"/> instance.</returns>
 55            /// <remarks>
 56            /// Parsed query values are written into <see cref="RequestContext.Parameters"/>. If that dictionary
 57            /// already contains the same key because of route binding, JSON binding, or earlier middleware, the
 58            /// query binding overwrites the existing value.
 59            /// </remarks>
 60            public TBuilder AddQueryBindings(IEnumerable<string> verbs, string bindings)
 161            {
 162                Ensure.NotNull(routeBuilder);
 163                Ensure.NotNull(verbs);
 164                Ensure.NotNull(bindings);
 65
 166                return routeBuilder.AddQueryBindings(verbs, "/", bindings);
 67            }
 68
 69            /// <summary>
 70            /// Parses configured query parameters and stores their values in <see cref="RequestContext.Parameters"/>.
 71            /// </summary>
 72            /// <param name="pattern">
 73            /// The route pattern where the query-binding middleware should be inserted. Use <c>/</c> to apply it to
 74            /// the whole pipeline, or a narrower prefix/exact pattern to scope query binding to selected routes.
 75            /// </param>
 76            /// <param name="bindings">
 77            /// A query-parameter descriptor such as <c>{filter:str(min=3)}&amp;{page?:int(min=1)}</c>.
 78            /// </param>
 79            /// <returns>The current <paramref name="routeBuilder"/> instance.</returns>
 80            /// <remarks>
 81            /// Parsed query values are written into <see cref="RequestContext.Parameters"/>. If that dictionary
 82            /// already contains the same key because of route binding, JSON binding, or earlier middleware, the
 83            /// query binding overwrites the existing value.
 84            /// </remarks>
 85            public TBuilder AddQueryBindings(string pattern, string bindings)
 186            {
 187                Ensure.NotNull(routeBuilder);
 188                Ensure.NotNull(pattern);
 189                Ensure.NotNull(bindings);
 90
 191                return routeBuilder.AddQueryBindings
 192                (
 193                    Enum.GetNames(typeof(HttpVerb)),
 194                    pattern,
 195                    bindings
 196                );
 97            }
 98
 99            /// <summary>
 100            /// Parses configured query parameters and stores their values in <see cref="RequestContext.Parameters"/>.
 101            /// </summary>
 102            /// <param name="verb">The HTTP method that activates the query-binding middleware.</param>
 103            /// <param name="pattern">
 104            /// The route pattern where the query-binding middleware should be inserted. Use <c>/</c> to apply it to
 105            /// the whole pipeline, or a narrower prefix/exact pattern to scope query binding to selected routes.
 106            /// </param>
 107            /// <param name="bindings">
 108            /// A query-parameter descriptor such as <c>{filter:str(min=3)}&amp;{page?:int(min=1)}</c>.
 109            /// </param>
 110            /// <returns>The current <paramref name="routeBuilder"/> instance.</returns>
 111            /// <remarks>
 112            /// Parsed query values are written into <see cref="RequestContext.Parameters"/>. If that dictionary
 113            /// already contains the same key because of route binding, JSON binding, or earlier middleware, the
 114            /// query binding overwrites the existing value.
 115            /// </remarks>
 116            public TBuilder AddQueryBindings(string verb, string pattern, string bindings)
 1117            {
 1118                Ensure.NotNull(routeBuilder);
 1119                Ensure.NotNull(verb);
 1120                Ensure.NotNull(pattern);
 1121                Ensure.NotNull(bindings);
 122
 1123                return routeBuilder.AddQueryBindings([verb], pattern, bindings);
 124            }
 125
 126            /// <summary>
 127            /// Parses configured query parameters and stores their values in <see cref="RequestContext.Parameters"/>.
 128            /// </summary>
 129            /// <param name="verbs">The HTTP methods that activate the query-binding middleware.</param>
 130            /// <param name="pattern">
 131            /// The route pattern where the query-binding middleware should be inserted. Use <c>/</c> to apply it to
 132            /// the whole pipeline, or a narrower prefix/exact pattern to scope query binding to selected routes.
 133            /// </param>
 134            /// <param name="bindings">
 135            /// A query-parameter descriptor such as <c>{filter:str(min=3)}&amp;{page?:int(min=1)}</c>.
 136            /// </param>
 137            /// <returns>The current <paramref name="routeBuilder"/> instance.</returns>
 138            /// <remarks>
 139            /// Parsed query values are written into <see cref="RequestContext.Parameters"/>. If that dictionary
 140            /// already contains the same key because of route binding, JSON binding, or earlier middleware, the
 141            /// query binding overwrites the existing value.
 142            /// </remarks>
 143            public TBuilder AddQueryBindings(IEnumerable<string> verbs, string pattern, string bindings)
 1144            {
 1145                Ensure.NotNull(routeBuilder);
 1146                Ensure.NotNull(verbs);
 1147                Ensure.NotNull(pattern);
 1148                Ensure.NotNull(bindings);
 149
 1150                Dictionary<ReadOnlyMemory<char>, ParameterParser> parsedBindingsTmp = new(ReadOnlyMemoryCharComparer.Ins
 151
 1152                foreach (ParameterDefinition parameterDefinition in RoutePatternParser.ParseQueryPattern(bindings))
 1153                {
 1154                    if (!routeBuilder.ValueParsers.TryGetValue(parameterDefinition.ValueParser.Name, out ValueParserRegi
 1155                        throw new InvalidOperationException
 1156                        (
 1157                            string.Format(Resources.Culture, Resources.ERR_NO_SUCH_PARSER, parameterDefinition.ValuePars
 1158                        );
 159
 1160                    parsedBindingsTmp.Add
 1161                    (
 1162                        parameterDefinition.ParameterName!.AsMemory(),
 1163                        new ParameterParser
 1164                        (
 1165                            parameterDefinition,
 1166                            parserRegistration.Parse,
 1167                            parserRegistration.BindArguments(parameterDefinition.ValueParser.RawArguments)
 1168                        )
 1169                    );
 1170                }
 171
 1172                IReadOnlyDictionary<ReadOnlyMemory<char>, ParameterParser> parsedBindings = parsedBindingsTmp.ToFrozenDi
 173
 1174                routeBuilder.AddHandler(verbs, pattern, async (RequestContext context, CallNextHandlerDelegate next) =>
 1175                {
 1176                    using QueryStringParser queryStringParser = new(context, parsedBindings);
 1177
 1178                    await queryStringParser.Parse();
 1179
 1180                    return await next();
 1181                });
 182
 1183                return routeBuilder;
 184            }
 185        }
 186    }
 187}