< Summary - Kestrun — Combined Coverage

Information
Class: Kestrun.Hosting.KestrunSecurityMiddlewareExtensions
Assembly: Kestrun
File(s): /home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/Hosting/KestrunSecurityMiddlewareExtensions.cs
Tag: Kestrun/Kestrun@0d738bf294e6281b936d031e1979d928007495ff
Line coverage
66%
Covered lines: 83
Uncovered lines: 41
Coverable lines: 124
Total lines: 337
Line coverage: 66.9%
Branch coverage
37%
Covered branches: 18
Total branches: 48
Branch coverage: 37.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 10/17/2025 - 15:48:30 Line coverage: 66.3% (63/95) Branch coverage: 42.5% (17/40) Total lines: 259 Tag: Kestrun/Kestrun@b8199aff869a847b75e185d0527ba45e04a43d8612/14/2025 - 20:04:52 Line coverage: 67.7% (82/121) Branch coverage: 39.1% (18/46) Total lines: 334 Tag: Kestrun/Kestrun@a05ac8de57c6207e227b92ba360e9d58869ac80a12/15/2025 - 02:23:46 Line coverage: 68.5% (83/121) Branch coverage: 39.1% (18/46) Total lines: 334 Tag: Kestrun/Kestrun@7a3839f4de2254e22daae81ab8dc7cb2f40c833012/18/2025 - 21:41:58 Line coverage: 66.9% (83/124) Branch coverage: 37.5% (18/48) Total lines: 337 Tag: Kestrun/Kestrun@0d738bf294e6281b936d031e1979d928007495ff 10/17/2025 - 15:48:30 Line coverage: 66.3% (63/95) Branch coverage: 42.5% (17/40) Total lines: 259 Tag: Kestrun/Kestrun@b8199aff869a847b75e185d0527ba45e04a43d8612/14/2025 - 20:04:52 Line coverage: 67.7% (82/121) Branch coverage: 39.1% (18/46) Total lines: 334 Tag: Kestrun/Kestrun@a05ac8de57c6207e227b92ba360e9d58869ac80a12/15/2025 - 02:23:46 Line coverage: 68.5% (83/121) Branch coverage: 39.1% (18/46) Total lines: 334 Tag: Kestrun/Kestrun@7a3839f4de2254e22daae81ab8dc7cb2f40c833012/18/2025 - 21:41:58 Line coverage: 66.9% (83/124) Branch coverage: 37.5% (18/48) Total lines: 337 Tag: Kestrun/Kestrun@0d738bf294e6281b936d031e1979d928007495ff

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
AddRateLimiter(...)50%6677.77%
AddRateLimiter(...)16.66%7666.66%
AddAntiforgery(...)75%5464.28%
AddAntiforgery(...)12.5%25835.71%
AddCorsDefaultPolicy(...)0%2260%
AddCorsPolicyName(...)50%9657.14%
AddCorsDefaultPolicy(...)0%2285.71%
AddCorsPolicyAllowAll(...)100%11100%
AddCorsDefaultPolicyAllowAll(...)100%11100%
AddCorsPolicy(...)0%2263.63%
AddCorsPolicy(...)50%2287.5%
AddHostFiltering(...)0%2040%
AddHostFiltering(...)100%66100%

File(s)

/home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/Hosting/KestrunSecurityMiddlewareExtensions.cs

#LineLine coverage
 1using Kestrun.Utilities;
 2using Microsoft.AspNetCore.Antiforgery;
 3using Microsoft.AspNetCore.Cors.Infrastructure;
 4using Microsoft.AspNetCore.RateLimiting;
 5using Serilog.Events;
 6using Microsoft.AspNetCore.HostFiltering;
 7
 8namespace Kestrun.Hosting;
 9
 10/// <summary>
 11/// Extension methods for adding security-related middleware to a <see cref="KestrunHost"/>.
 12/// </summary>
 13public static class KestrunSecurityMiddlewareExtensions
 14{
 15    /// <summary>
 16    /// Adds rate limiting to the application using the specified <see cref="RateLimiterOptions"/>.
 17    /// </summary>
 18    /// <param name="host">The KestrunHost instance to configure.</param>
 19    /// <param name="cfg">The configuration options for rate limiting.</param>
 20    /// <returns>The current KestrunHost instance.</returns>
 21    public static KestrunHost AddRateLimiter(this KestrunHost host, RateLimiterOptions cfg)
 22    {
 223        if (host.Logger.IsEnabled(LogEventLevel.Debug))
 24        {
 025            host.Logger.Debug("Adding rate limiter with configuration: {@Config}", cfg);
 26        }
 27
 228        if (cfg == null)
 29        {
 130            return host.AddRateLimiter();   // fall back to your “blank” overload
 31        }
 32
 133        _ = host.AddService(services =>
 134        {
 035            _ = services.AddRateLimiter(opts => opts.CopyFrom(cfg));   // ← single line!
 136        });
 37
 138        return host.Use(app => app.UseRateLimiter());
 39    }
 40
 41    /// <summary>
 42    /// Adds rate limiting to the application using the specified configuration delegate.
 43    /// </summary>
 44    /// <param name="host">The KestrunHost instance to configure.</param>
 45    /// <param name="cfg">An optional delegate to configure rate limiting options.</param>
 46    /// <returns>The current KestrunHost instance.</returns>
 47    public static KestrunHost AddRateLimiter(this KestrunHost host, Action<RateLimiterOptions>? cfg = null)
 48    {
 349        if (host.Logger.IsEnabled(LogEventLevel.Debug))
 50        {
 051            host.Logger.Debug("Adding rate limiter with configuration: {HasConfig}", cfg != null);
 52        }
 53
 54        // Register the rate limiter service
 355        _ = host.AddService(services =>
 356            {
 057                _ = services.AddRateLimiter(cfg ?? (_ => { })); // Always pass a delegate
 358            });
 59
 60        // Apply the middleware
 361        return host.Use(app =>
 362        {
 063            if (host.Logger.IsEnabled(LogEventLevel.Debug))
 364            {
 065                host.Logger.Debug("Registering rate limiter middleware");
 366            }
 367
 068            _ = app.UseRateLimiter();
 369        });
 70    }
 71
 72    /// <summary>
 73    /// Adds antiforgery protection to the application.
 74    /// This overload allows you to specify configuration options.
 75    /// </summary>
 76    /// <param name="host">The KestrunHost instance to configure.</param>
 77    /// <param name="options">The antiforgery options to configure.</param>
 78    /// <returns>The current KestrunHost instance.</returns>
 79    public static KestrunHost AddAntiforgery(this KestrunHost host, AntiforgeryOptions? options)
 80    {
 281        if (host.Logger.IsEnabled(LogEventLevel.Debug))
 82        {
 083            host.Logger.Debug("Adding Antiforgery with configuration: {@Config}", options);
 84        }
 85
 286        if (options == null)
 87        {
 188            return host.AddAntiforgery(); // no config, use defaults
 89        }
 90
 91        // Delegate to the Action-based overload
 192        return host.AddAntiforgery(cfg =>
 193        {
 094            cfg.Cookie = options.Cookie;
 095            cfg.FormFieldName = options.FormFieldName;
 096            cfg.HeaderName = options.HeaderName;
 097            cfg.SuppressXFrameOptionsHeader = options.SuppressXFrameOptionsHeader;
 198#if NET9_0_OR_GREATER
 199            cfg.SuppressReadingTokenFromFormBody = options.SuppressReadingTokenFromFormBody;
 1100#endif
 1101        });
 102    }
 103
 104    /// <summary>
 105    /// Adds antiforgery protection to the application.
 106    /// </summary>
 107    /// <param name="host">The KestrunHost instance to configure.</param>
 108    /// <param name="setupAction">An optional action to configure the antiforgery options.</param>
 109    /// <returns>The current KestrunHost instance.</returns>
 110    public static KestrunHost AddAntiforgery(this KestrunHost host, Action<AntiforgeryOptions>? setupAction = null)
 111    {
 4112        if (host.Logger.IsEnabled(LogEventLevel.Debug))
 113        {
 0114            host.Logger.Debug(
 0115                setupAction == null
 0116                    ? "Adding Antiforgery with default configuration (no custom options provided)."
 0117                    : "Adding Antiforgery with custom configuration via setupAction."
 0118            );
 119        }
 120        // Service side
 4121        _ = host.AddService(services =>
 4122        {
 0123            var options = new AntiforgeryOptions();
 0124            setupAction?.Invoke(options);
 0125            host.AntiforgeryOptions = options;
 0126            _ = setupAction == null ? services.AddAntiforgery() : services.AddAntiforgery(setupAction);
 4127        });
 128
 129        // Middleware side
 4130        return host.Use(app => app.UseAntiforgery());
 131    }
 132
 133    /// <summary>
 134    /// Adds a default CORS policy to the application using the specified <see cref="CorsPolicyBuilder"/>.
 135    /// </summary>
 136    /// <param name="host"> The KestrunHost instance to configure.</param>
 137    /// <param name="builder">The CORS policy builder to use for the default policy.</param>
 138    /// <returns>The current KestrunHost instance.</returns>
 139    public static KestrunHost AddCorsDefaultPolicy(this KestrunHost host, CorsPolicyBuilder builder)
 140    {
 2141        ArgumentNullException.ThrowIfNull(builder);
 142        // The name of the default policy is hardcoded here.
 143        const string defaultPolicyName = "__DefaultPolicy__";
 144        // Service‑time registration
 1145        _ = host.AddService(services =>
 1146        {
 0147            _ = services.AddCors(options =>
 0148            {
 0149                options.AddDefaultPolicy(builder.Build());
 0150            });
 1151        });
 152
 153        // Add the policy name to the list of defined policies
 1154        host.AddCorsPolicyName(defaultPolicyName);
 155
 1156        return host;
 157    }
 158
 159    /// <summary>
 160    /// Adds a named CORS policy to the application.
 161    /// </summary>
 162    /// <param name="host">The KestrunHost instance to configure.</param>
 163    /// <param name="policyName">The name to store/apply the policy under.</param>
 164    private static void AddCorsPolicyName(this KestrunHost host, string policyName)
 165    {
 14166        if (host.Logger.IsEnabled(LogEventLevel.Debug))
 167        {
 0168            host.Logger.Debug("Adding CORS policy: {PolicyName}", policyName);
 169        }
 14170        if (host.DefinedCorsPolicyNames.Contains(policyName))
 171        {
 0172            if (host.Logger.IsEnabled(LogEventLevel.Warning))
 173            {
 0174                host.Logger.Warning("CORS policy '{PolicyName}' is already defined.", policyName);
 175            }
 176        }
 177        else
 178        {
 14179            host.DefinedCorsPolicyNames.Add(policyName);
 180        }
 14181    }
 182    /// <summary>
 183    /// Adds a default CORS policy to the application using the specified configuration delegate.
 184    /// </summary>
 185    /// <param name="host"> The KestrunHost instance to configure.</param>
 186    /// <param name="buildPolicy">An action to configure the CORS policy.</param>
 187    /// <returns>The current KestrunHost instance.</returns>
 188    public static KestrunHost AddCorsDefaultPolicy(this KestrunHost host, Action<CorsPolicyBuilder> buildPolicy)
 189    {
 5190        ArgumentNullException.ThrowIfNull(buildPolicy);
 191        // The name of the default policy is hardcoded here.
 192        const string defaultPolicyName = "__DefaultPolicy__";
 193
 4194        _ = host.AddService(services =>
 4195        {
 0196            _ = services.AddCors(options => options.AddDefaultPolicy(buildPolicy));
 4197        });
 198
 199        // Add the policy name to the list of defined policies
 4200        host.AddCorsPolicyName(defaultPolicyName);
 4201        return host;
 202    }
 203
 204    /// <summary>
 205    /// Adds a CORS policy named "AllowAll" that allows any origin, method, and header.
 206    /// </summary>
 207    /// <param name="host">The KestrunHost instance to configure.</param>
 208    /// <param name="policyName">The name to store/apply the policy under.</param>
 209    /// <returns>The current KestrunHost instance.</returns>
 210    public static KestrunHost AddCorsPolicyAllowAll(this KestrunHost host, string policyName) =>
 2211        host.AddCorsPolicy(policyName, b => b.AllowAnyOrigin()
 2212                                  .AllowAnyMethod()
 2213                                  .AllowAnyHeader());
 214
 215    /// <summary>
 216    /// Adds a default CORS policy that allows any origin, method, and header.
 217    /// </summary>
 218    /// <param name="host">The KestrunHost instance to configure.</param>
 219    /// <returns>The current KestrunHost instance.</returns>
 220    public static KestrunHost AddCorsDefaultPolicyAllowAll(this KestrunHost host) =>
 3221        host.AddCorsDefaultPolicy(b => b.AllowAnyOrigin()
 3222                                    .AllowAnyMethod()
 3223                                    .AllowAnyHeader());
 224
 225    /// <summary>
 226    /// Registers a named CORS policy that was already composed with a
 227    /// <see cref="CorsPolicyBuilder"/> and applies that policy in the pipeline.
 228    /// </summary>
 229    /// <param name="host">The KestrunHost instance to configure.</param>
 230    /// <param name="policyName">The name to store/apply the policy under.</param>
 231    /// <param name="builder">
 232    ///     A fully‑configured <see cref="CorsPolicyBuilder"/>.
 233    ///     Callers typically chain <c>.WithOrigins()</c>, <c>.WithMethods()</c>,
 234    ///     etc. before passing it here.
 235    /// </param>
 236    public static KestrunHost AddCorsPolicy(this KestrunHost host, string policyName, CorsPolicyBuilder builder)
 237    {
 13238        ArgumentException.ThrowIfNullOrWhiteSpace(policyName);
 11239        ArgumentNullException.ThrowIfNull(builder);
 240
 241        // Service‑time registration
 9242        _ = host.AddService(services =>
 9243        {
 0244            _ = services.AddCors(options =>
 0245            {
 0246                options.AddPolicy(policyName, builder.Build());
 0247            });
 9248        });
 249
 250        // Add the policy name to the list of defined policies
 9251        host.AddCorsPolicyName(policyName);
 252
 253        // 2️⃣ Middleware‑time application
 9254        return host;
 255    }
 256
 257    /// <summary>
 258    /// Registers a named CORS policy that was already composed with a
 259    /// <see cref="CorsPolicyBuilder"/> and applies that policy in the pipeline.
 260    /// </summary>
 261    /// <param name="host">The KestrunHost instance to configure.</param>
 262    /// <param name="policyName">The name to store/apply the policy under.</param>
 263    /// <param name="buildPolicy">An action to configure the CORS policy.</param>
 264    /// <returns>The current KestrunHost instance.</returns>
 265    /// <exception cref="ArgumentException">Thrown when the policy name is null or whitespace.</exception>
 266    public static KestrunHost AddCorsPolicy(this KestrunHost host, string policyName, Action<CorsPolicyBuilder> buildPol
 267    {
 11268        ArgumentNullException.ThrowIfNull(host);
 11269        ArgumentException.ThrowIfNullOrWhiteSpace(policyName);
 270
 9271        if (host.Logger.IsEnabled(LogEventLevel.Debug))
 272        {
 0273            host.Logger.Debug("Adding CORS policy: {PolicyName}", policyName);
 274        }
 275
 9276        ArgumentNullException.ThrowIfNull(buildPolicy);
 7277        var builder = new CorsPolicyBuilder();
 7278        buildPolicy(builder);
 279
 7280        return host.AddCorsPolicy(policyName, builder);
 281    }
 282
 283    /// <summary>
 284    /// Adds Host Filtering to the application using the specified configuration delegate.
 285    /// </summary>
 286    /// <param name="host">The KestrunHost instance to configure.</param>
 287    /// <param name="opts">The delegate for configuring host filtering options.</param>
 288    /// <returns>The updated KestrunHost instance.</returns>
 289    public static KestrunHost AddHostFiltering(this KestrunHost host, Action<HostFilteringOptions>? opts = null)
 290    {
 0291        if (host.Logger.IsEnabled(LogEventLevel.Debug))
 292        {
 0293            host.Logger.Debug("Adding host filtering with configuration: {HostFilteringOptions}", opts != null);
 294        }
 295
 296        // Register the host filtering service
 0297        _ = host.AddService(services =>
 0298            {
 0299                _ = services.AddHostFiltering(opts ?? (_ => { })); // Always pass a delegate
 0300            });
 301
 302        // Apply the middleware
 0303        return host.Use(app => app.UseHostFiltering());
 304    }
 305
 306    /// <summary>
 307    /// Adds Host Filtering to the application using the specified <see cref="HostFilteringOptions"/>.
 308    /// </summary>
 309    /// <param name="host">The KestrunHost instance to configure.</param>
 310    /// <param name="opts">The host filtering options.</param>
 311    /// <returns>The updated KestrunHost instance.</returns>
 312    public static KestrunHost AddHostFiltering(this KestrunHost host, HostFilteringOptions opts)
 313    {
 1314        if (host.Logger.IsEnabled(LogEventLevel.Debug))
 315        {
 1316            host.Logger.Debug("Adding host filtering with configuration: {HostFilteringOptions}", opts);
 317        }
 318
 319        // Register the host filtering service
 1320        _ = host.AddService(services =>
 1321        {
 1322            _ = services.AddHostFiltering(o =>
 1323            {
 1324                o.AllowedHosts.Clear();
 4325                foreach (var host in opts.AllowedHosts)
 1326                {
 1327                    o.AllowedHosts.Add(host);
 1328                }
 1329                o.AllowEmptyHosts = opts.AllowEmptyHosts;
 1330                o.IncludeFailureMessage = opts.IncludeFailureMessage;
 2331            });
 2332        });
 333
 334        // Apply the middleware
 2335        return host.Use(app => app.UseHostFiltering());
 336    }
 337}