Static Files
Arc.Core provides built-in support for serving static files, similar to the UseStaticFiles() middleware in ASP.NET Core. This is essential for hosting Single Page Applications (SPAs), serving assets like CSS, JavaScript, images, and other static content.
Basic Usage
Section titled “Basic Usage”To serve static files from the default wwwroot directory:
var builder = ArcApplication.CreateBuilder(args);builder.AddCratisArc();
var app = builder.Build();
// Enable static file serving from wwwrootapp.UseStaticFiles();
app.UseCratisArc();await app.RunAsync();Important:
UseStaticFiles()must be called beforeUseCratisArc()to ensure the static file configuration is registered before the HTTP listener starts.
Configuration Options
Section titled “Configuration Options”You can customize static file serving using StaticFileOptions:
app.UseStaticFiles(options =>{ // Serve files from a custom directory options.FileSystemPath = "public";
// Add a URL prefix for static files options.RequestPath = "/static";
// Enable/disable serving default files (index.html, etc.) options.ServeDefaultFiles = true;
// Customize which files are considered "default" files options.DefaultFileNames = ["index.html", "default.html"];
// Add custom MIME type mappings options.ContentTypeMappings["myext"] = "application/x-custom";});StaticFileOptions Properties
Section titled “StaticFileOptions Properties”| Property | Type | Default | Description |
|---|---|---|---|
FileSystemPath | string | "wwwroot" | The directory to serve files from |
RequestPath | string | "" (root) | URL prefix for static file requests |
ServeDefaultFiles | bool | true | Whether to serve index.html for directory requests |
DefaultFileNames | IList<string> | ["index.html", "index.htm", "default.html", "default.htm"] | Files to look for when requesting a directory |
EnableDirectoryBrowsing | bool | false | Whether to allow directory listing (not yet implemented) |
ContentTypeMappings | IDictionary<string, string> | Empty | Custom file extension to MIME type mappings |
File System Path Resolution
Section titled “File System Path Resolution”Arc.Core resolves relative paths in the following order:
-
Current Working Directory - First checks if the path exists relative to
Directory.GetCurrentDirectory(). This is typically your project directory when running withdotnet run. -
Application Base Directory - Falls back to
AppContext.BaseDirectory(thebin/Debug/net10.0/output folder) if not found in the current directory.
This behavior matches how ASP.NET Core resolves content root paths during development and ensures your wwwroot folder is found whether you’re running from the project directory or from the compiled output.
Example: Custom Static Directory
Section titled “Example: Custom Static Directory”// Serve from 'public' folder in your project directoryapp.UseStaticFiles(options =>{ options.FileSystemPath = "public";});
// Serve from an absolute pathapp.UseStaticFiles(options =>{ options.FileSystemPath = "/var/www/static";});SPA Fallback with MapFallbackToFile
Section titled “SPA Fallback with MapFallbackToFile”For Single Page Applications that use client-side routing, you need to serve your index.html for any route that doesn’t match a static file or API endpoint. Use MapFallbackToFile():
var app = builder.Build();
// Serve static filesapp.UseStaticFiles();
// Fallback to index.html for SPA routingapp.MapFallbackToFile(); // Defaults to "index.html"
// Or specify a custom fileapp.MapFallbackToFile("app.html");
app.UseCratisArc();await app.RunAsync();The fallback file is served when:
- No registered API route matches the request
- No static file matches the request path
- The request method is GET
- The fallback file exists in the static files directory
Complete SPA Example
Section titled “Complete SPA Example”Here’s a complete example for hosting a React, Angular, or Vue SPA:
using Cratis.Arc;
var builder = ArcApplication.CreateBuilder(args);builder.AddCratisArc();
var app = builder.Build();
// Serve static files from wwwrootapp.UseStaticFiles();
// Enable SPA fallback routingapp.MapFallbackToFile();
// Configure Arc (maps API endpoints)app.UseCratisArc();
await app.RunAsync();With this configuration:
/→ Serveswwwroot/index.html/styles.css→ Serveswwwroot/styles.css/js/app.js→ Serveswwwroot/js/app.js/dashboard/users/123→ Serveswwwroot/index.html(SPA route)/api/users→ Handled by your query endpoints
Multiple Static File Configurations
Section titled “Multiple Static File Configurations”You can call UseStaticFiles() multiple times to serve from different directories:
// Serve from wwwroot at rootapp.UseStaticFiles();
// Serve uploaded files from a different directoryapp.UseStaticFiles(options =>{ options.FileSystemPath = "uploads"; options.RequestPath = "/files";});Middleware Order
Section titled “Middleware Order”The order of middleware configuration is important:
var app = builder.Build();
// 1. Static files (first, so static assets are served quickly)app.UseStaticFiles();
// 2. SPA fallback (after static files, before API routes)app.MapFallbackToFile();
// 3. Arc configuration (API routes, etc.)app.UseCratisArc();
await app.RunAsync();MIME Types
Section titled “MIME Types”Arc.Core includes built-in MIME type mappings for common file extensions:
| Category | Extensions |
|---|---|
| Text | .txt, .html, .htm, .css, .csv, .xml |
| JavaScript | .js, .mjs, .jsx, .ts, .tsx |
| JSON | .json, .map |
| Images | .png, .jpg, .jpeg, .gif, .svg, .webp, .ico |
| Fonts | .woff, .woff2, .ttf, .otf, .eot |
| Documents | .pdf, .doc, .docx, .xls, .xlsx |
| Audio | .mp3, .wav, .ogg, .m4a |
| Video | .mp4, .webm, .avi, .mov |
| Web | .wasm, .webmanifest |
For unknown extensions, application/octet-stream is returned.
Adding Custom MIME Types
Section titled “Adding Custom MIME Types”app.UseStaticFiles(options =>{ options.ContentTypeMappings[".custom"] = "application/x-custom"; options.ContentTypeMappings[".data"] = "application/octet-stream";});Security
Section titled “Security”Arc.Core includes protection against directory traversal attacks. Requests attempting to access files outside the configured static file directory (e.g., /../../../etc/passwd) will return a 404 response.