< Summary - Kestrun — Combined Coverage

Information
Class: Kestrun.Hosting.KestrunHostStaticFilesExtensions
Assembly: Kestrun
File(s): /home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/Hosting/KestrunHostStaticFilesExtensions.cs
Tag: Kestrun/Kestrun@2d87023b37eb91155071c91dd3d6a2eeb3004705
Line coverage
42%
Covered lines: 61
Uncovered lines: 83
Coverable lines: 144
Total lines: 310
Line coverage: 42.3%
Branch coverage
24%
Covered branches: 14
Total branches: 58
Branch coverage: 24.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 08/26/2025 - 01:25:22 Line coverage: 57.6% (53/92) Branch coverage: 41.1% (14/34) Total lines: 247 Tag: Kestrun/Kestrun@07f821172e5dc3657f1be7e6818f18d6721cf38a08/29/2025 - 19:03:16 Line coverage: 55.2% (53/96) Branch coverage: 41.1% (14/34) Total lines: 261 Tag: Kestrun/Kestrun@bbe80beb98bdf6ba9249a033d00f6e4748a4c06c09/14/2025 - 21:23:16 Line coverage: 42.3% (61/144) Branch coverage: 24.1% (14/58) Total lines: 310 Tag: Kestrun/Kestrun@c9d2f0b3dd164d7dc0dc2407a9f006293d924223 08/26/2025 - 01:25:22 Line coverage: 57.6% (53/92) Branch coverage: 41.1% (14/34) Total lines: 247 Tag: Kestrun/Kestrun@07f821172e5dc3657f1be7e6818f18d6721cf38a08/29/2025 - 19:03:16 Line coverage: 55.2% (53/96) Branch coverage: 41.1% (14/34) Total lines: 261 Tag: Kestrun/Kestrun@bbe80beb98bdf6ba9249a033d00f6e4748a4c06c09/14/2025 - 21:23:16 Line coverage: 42.3% (61/144) Branch coverage: 24.1% (14/58) Total lines: 310 Tag: Kestrun/Kestrun@c9d2f0b3dd164d7dc0dc2407a9f006293d924223

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
AddDefaultFiles(...)75%4475%
AddDefaultFiles(...)50%22100%
AddDirectoryBrowser(...)100%210%
AddFavicon(...)100%11100%
CopyStaticFileOptions(...)0%2040%
CopyDefaultFilesOptions(...)0%4260%
AddFileServer(...)16.66%1351828.88%
AddFileServer(...)50%4487.5%
AddStaticFiles(...)50%4487.5%
AddStaticFiles(...)18.75%921633.33%

File(s)

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

#LineLine coverage
 1
 2using Kestrun.Middleware;
 3using Microsoft.Net.Http.Headers;
 4using Serilog.Events;
 5
 6namespace Kestrun.Hosting;
 7
 8/// <summary>
 9/// Provides extension methods for configuring static file, default file, favicon, and file server middleware in Kestrun
 10/// </summary>
 11public static class KestrunHostStaticFilesExtensions
 12{
 13    /// <summary>
 14    /// Adds default files middleware to the application.
 15    /// This middleware serves default files like index.html when a directory is requested.
 16    /// </summary>
 17    /// <param name="host">The KestrunHost instance to configure.</param>
 18    /// <param name="cfg">Configuration options for the default files middleware.</param>
 19    /// <returns>The current KestrunHost instance.</returns>
 20    public static KestrunHost AddDefaultFiles(this KestrunHost host, DefaultFilesOptions? cfg)
 21    {
 222        if (host.Logger.IsEnabled(LogEventLevel.Debug))
 23        {
 024            host.Logger.Debug("Adding Default Files with configuration: {@Config}", cfg);
 25        }
 26
 227        if (cfg == null)
 28        {
 129            return host.AddDefaultFiles(); // no config, use defaults
 30        }
 31
 32        // Convert DefaultFilesOptions to an Action<DefaultFilesOptions>
 133        return host.AddDefaultFiles(options =>
 134        {
 035            CopyDefaultFilesOptions(cfg, options);
 136        });
 37    }
 38
 39    /// <summary>
 40    /// Adds default files middleware to the application.
 41    /// This middleware serves default files like index.html when a directory is requested.
 42    /// </summary>
 43    /// <param name="host">The KestrunHost instance to configure.</param>
 44    /// <param name="cfg">Configuration options for the default files middleware.</param>
 45    /// <returns>The current KestrunHost instance.</returns>
 46    public static KestrunHost AddDefaultFiles(this KestrunHost host, Action<DefaultFilesOptions>? cfg = null)
 47    {
 548        return host.Use(app =>
 549        {
 150            var options = new DefaultFilesOptions();
 151            cfg?.Invoke(options);
 152            _ = app.UseDefaultFiles(options);
 653        });
 54    }
 55
 56    /// <summary>
 57    /// Adds a directory browser middleware to the application.
 58    /// This middleware enables directory browsing for a specified request path.
 59    /// </summary>
 60    /// <param name="host">The KestrunHost instance to configure.</param>
 61    /// <param name="requestPath">The request path to enable directory browsing for.</param>
 62    /// <returns>The current KestrunHost instance.</returns>
 63    public static KestrunHost AddDirectoryBrowser(this KestrunHost host, string requestPath)
 64    {
 065        return host.Use(app =>
 066        {
 067            _ = app.UseDirectoryBrowser(requestPath);
 068        });
 69    }
 70
 71    /// <summary>
 72    /// Adds a favicon middleware to the application.
 73    /// </summary>
 74    /// <param name="host">The KestrunHost instance to configure.</param>
 75    /// <param name="iconPath">The path to the favicon file. If null, uses the default favicon.</param>
 76    /// <returns>The current KestrunHost instance.</returns>
 77    public static KestrunHost AddFavicon(this KestrunHost host, string? iconPath = null)
 78    {
 479        return host.Use(app =>
 480        {
 281            _ = app.UseFavicon(iconPath);
 682        });
 83    }
 84
 85
 86    /// <summary>
 87    /// Copies static file options from one object to another.
 88    /// </summary>
 89    /// <param name="src">The source static file options.</param>
 90    /// <param name="dest">The destination static file options.</param>
 91    /// <remarks>
 92    /// This method copies properties from the source static file options to the destination static file options.
 93    /// </remarks>
 94    private static void CopyStaticFileOptions(StaticFileOptions? src, StaticFileOptions dest)
 95    {
 96        // If no source, return a new empty options object
 097        if (src == null || dest == null)
 98        {
 099            return;
 100        }
 101        // Copy properties from source to destination
 0102        dest.ContentTypeProvider = src.ContentTypeProvider;
 0103        dest.OnPrepareResponse = src.OnPrepareResponse;
 0104        dest.ServeUnknownFileTypes = src.ServeUnknownFileTypes;
 0105        dest.DefaultContentType = src.DefaultContentType;
 0106        dest.FileProvider = src.FileProvider;
 0107        dest.RequestPath = src.RequestPath;
 0108        dest.RedirectToAppendTrailingSlash = src.RedirectToAppendTrailingSlash;
 0109        dest.HttpsCompression = src.HttpsCompression;
 0110    }
 111
 112    /// <summary>
 113    /// Copies default files options from one object to another.
 114    /// This method is used to ensure that the default files options are correctly configured.
 115    /// </summary>
 116    /// <param name="src">The source default files options.</param>
 117    /// <param name="dest">The destination default files options.</param>
 118    /// <remarks>
 119    /// This method copies properties from the source default files options to the destination default files options.
 120    /// </remarks>
 121    private static void CopyDefaultFilesOptions(DefaultFilesOptions? src, DefaultFilesOptions dest)
 122    {
 123        // If no source, return a new empty options object
 0124        if (src == null || dest == null)
 125        {
 0126            return;
 127        }
 128        // Copy properties from source to destination
 0129        dest.DefaultFileNames.Clear();
 0130        foreach (var name in src.DefaultFileNames)
 131        {
 0132            dest.DefaultFileNames.Add(name);
 133        }
 134
 0135        dest.FileProvider = src.FileProvider;
 0136        dest.RequestPath = src.RequestPath;
 0137        dest.RedirectToAppendTrailingSlash = src.RedirectToAppendTrailingSlash;
 0138    }
 139
 140    /// <summary>
 141    /// Adds a file server middleware to the application.
 142    /// </summary>
 143    /// <param name="host">The KestrunHost instance to configure.</param>
 144    /// <param name="cfg">Configuration options for the file server middleware.</param>
 145    /// <param name="cacheControl">Optional cache control headers to apply to static file responses.</param>
 146    /// <returns>The current KestrunHost instance.</returns>
 147    /// <remarks>
 148    /// This middleware serves static files and default files from a specified file provider.
 149    /// If no configuration is provided, it uses default settings.
 150    /// </remarks>
 151    public static KestrunHost AddFileServer(this KestrunHost host, FileServerOptions? cfg, CacheControlHeaderValue? cach
 152    {
 2153        if (host.Logger.IsEnabled(LogEventLevel.Debug))
 154        {
 0155            host.Logger.Debug("Adding File Server with configuration: {@Config}", cfg);
 156        }
 157
 2158        if (cfg == null)
 159        {
 1160            return host.AddFileServer(); // no config, use defaults
 161        }
 162
 163        // Convert FileServerOptions to an Action<FileServerOptions>
 1164        return host.AddFileServer(options =>
 1165        {
 0166            options.EnableDefaultFiles = cfg.EnableDefaultFiles;
 0167            options.EnableDirectoryBrowsing = cfg.EnableDirectoryBrowsing;
 0168            options.FileProvider = cfg.FileProvider;
 0169            options.RequestPath = cfg.RequestPath;
 0170            options.RedirectToAppendTrailingSlash = cfg.RedirectToAppendTrailingSlash;
 0171            CopyDefaultFilesOptions(cfg.DefaultFilesOptions, options.DefaultFilesOptions);
 0172            if (cfg.DirectoryBrowserOptions != null)
 1173            {
 0174                options.DirectoryBrowserOptions.FileProvider = cfg.DirectoryBrowserOptions.FileProvider;
 0175                options.DirectoryBrowserOptions.RequestPath = cfg.DirectoryBrowserOptions.RequestPath;
 0176                options.DirectoryBrowserOptions.RedirectToAppendTrailingSlash = cfg.DirectoryBrowserOptions.RedirectToAp
 1177            }
 1178
 0179            CopyStaticFileOptions(cfg.StaticFileOptions, options.StaticFileOptions);
 0180            if (cacheControl != null)
 1181            {
 0182                options.StaticFileOptions.OnPrepareResponse = ctx =>
 0183                {
 0184                    // Apply the provided cache control if one was given
 0185                    if (host.Logger.IsEnabled(LogEventLevel.Debug))
 0186                    {
 0187                        host.Logger.Debug("Setting Cache-Control header to: {@CacheControl}", cacheControl);
 0188                    }
 0189                    ctx.Context.Response.Headers.CacheControl = cacheControl.ToString();
 0190                };
 1191            }
 0192            else if (host.DefaultCacheControl != null)
 1193            {
 0194                options.StaticFileOptions.OnPrepareResponse = ctx =>
 0195                {
 0196                    // Apply the host-wide default cache control if no specific one was provided
 0197                    if (host.Logger.IsEnabled(LogEventLevel.Debug))
 0198                    {
 0199                        host.Logger.Debug("Setting host-wide default cache Cache-Control: {@DefaultCacheControl}", host.
 0200                    }
 0201                    ctx.Context.Response.Headers.CacheControl = host.DefaultCacheControl.ToString();
 0202                };
 1203            }
 1204        });
 205    }
 206
 207    /// <summary>
 208    /// Adds a file server middleware to the application.
 209    /// This middleware serves static files and default files from a specified file provider.
 210    /// </summary>
 211    /// <param name="host">The KestrunHost instance to configure.</param>
 212    /// <param name="cfg">Configuration options for the file server middleware.</param>
 213    /// <returns>The current KestrunHost instance.</returns>
 214    public static KestrunHost AddFileServer(this KestrunHost host, Action<FileServerOptions>? cfg = null)
 215    {
 7216        if (host.Logger.IsEnabled(LogEventLevel.Debug))
 217        {
 0218            host.Logger.Debug("Adding File Server with Action<configuration>");
 219        }
 220
 7221        return host.Use(app =>
 7222        {
 2223            var options = new FileServerOptions();
 2224            cfg?.Invoke(options);
 2225            _ = app.UseFileServer(options);
 9226        });
 227    }
 228
 229    /// <summary>
 230    /// Adds static files to the application.
 231    /// This overload allows you to specify configuration options.
 232    /// </summary>
 233    /// <param name="host">The KestrunHost instance to configure.</param>
 234    /// <param name="cfg">The static file options to configure.</param>
 235    /// <returns>The current KestrunHost instance.</returns>
 236    public static KestrunHost AddStaticFiles(this KestrunHost host, Action<StaticFileOptions>? cfg = null)
 237    {
 8238        if (host.Logger.IsEnabled(LogEventLevel.Debug))
 239        {
 0240            host.Logger.Debug("Adding static files with configuration: {Config}", cfg);
 241        }
 242
 8243        return host.Use(app =>
 8244        {
 3245            if (cfg == null)
 8246            {
 0247                _ = app.UseStaticFiles();
 8248            }
 8249            else
 8250            {
 3251                var options = new StaticFileOptions();
 3252                cfg(options);
 8253
 3254                _ = app.UseStaticFiles(options);
 8255            }
 11256        });
 257    }
 258
 259    /// <summary>
 260    /// Adds static files to the application.
 261    /// This overload allows you to specify configuration options.
 262    /// </summary>
 263    /// <param name="host">The KestrunHost instance to configure.</param>
 264    /// <param name="options">The static file options to configure.</param>
 265    /// <param name="cacheControl">Optional cache control headers to apply to static file responses.</param>
 266    /// <returns>The current KestrunHost instance.</returns>
 267    public static KestrunHost AddStaticFiles(this KestrunHost host, StaticFileOptions options, CacheControlHeaderValue? 
 268    {
 2269        if (host.Logger.IsEnabled(LogEventLevel.Debug))
 270        {
 0271            host.Logger.Debug("Adding static files with options: {@Options} and cache control: {@CacheControl}", options
 272        }
 273
 2274        if (options == null)
 275        {
 1276            return host.AddStaticFiles(); // no options, use defaults
 277        }
 278
 279        // reuse the delegate overload so the pipeline logic stays in one place
 1280        return host.AddStaticFiles(o =>
 1281        {
 1282            // copy only the properties callers are likely to set
 0283            CopyStaticFileOptions(options, o);
 0284            if (cacheControl != null)
 1285            {
 0286                o.OnPrepareResponse = ctx =>
 0287                {
 0288                    // Apply the provided cache control if one was given
 0289                    if (host.Logger.IsEnabled(LogEventLevel.Debug))
 0290                    {
 0291                        host.Logger.Debug("Setting Cache-Control header to: {@CacheControl}", cacheControl);
 0292                    }
 0293                    ctx.Context.Response.Headers.CacheControl = cacheControl.ToString();
 0294                };
 1295            }
 0296            else if (host.DefaultCacheControl != null)
 1297            {
 0298                o.OnPrepareResponse = ctx =>
 0299                {
 0300                    // Apply the host-wide default cache control if no specific one was provided
 0301                    if (host.Logger.IsEnabled(LogEventLevel.Debug))
 0302                    {
 0303                        host.Logger.Debug("Setting host-wide default cache Cache-Control: {@DefaultCacheControl}", host.
 0304                    }
 0305                    ctx.Context.Response.Headers.CacheControl = host.DefaultCacheControl.ToString();
 0306                };
 1307            }
 1308        });
 309    }
 310}