Serving Static Files

Expose folders of files (HTML, CSS, JS, images, etc.) over HTTP using the static files service.

Prerequisites: see Introduction.

Full source

<#
    Sample Kestrun Server on how to use static routes.
    These examples demonstrate how to configure static routes in a Kestrun server.
    FileName: 3.1-Static-Routes.ps1
#>

# Import the Kestrun module
Install-PSResource -Name Kestrun

# Initialize Kestrun root directory
# the default value is $PWD
# This is recommended in order to use relative paths without issues
Initialize-KrRoot -Path $PSScriptRoot

# Create a new Kestrun server
New-KrServer -Name "Simple Server"

# Add a listener on port 5000 and IP address 127.0.0.1 (localhost)
Add-KrListener -Port 5000 -IPAddress ([IPAddress]::Loopback)

# Add a static files service
Add-KrStaticFilesService -RequestPath '/assets' -RootPath '.\Assets\wwwroot' -ServeUnknownFileTypes

# Enable Kestrun configuration
Enable-KrConfiguration

# Start the server asynchronously
Start-KrServer

Step-by-step

  1. Install & initialize:
    • Install-PSResource -Name Kestrun ensures the module is available.
    • Initialize-KrRoot -Path $PSScriptRoot sets a stable root so relative paths (like ./Assets/wwwroot) resolve even when the script is launched from a different working directory.
  2. Create the server and listener (New-KrServer, Add-KrListener) on 127.0.0.1:5000.
  3. Register the static file service with Add-KrStaticFilesService:

    • -RequestPath '/assets' makes files available under that URL prefix.
    • -RootPath '.\Assets\wwwroot' points to a folder (relative to the initialized root) that contains the files to serve.
    • -ServeUnknownFileTypes allows files with extensions not in the default MIME map to be served (they’ll use a default application/octet-stream unless overridden). Use cautiously; omit in production unless you need it.
  4. Enable configuration (Enable-KrConfiguration) so registered services/routes are materialized.
  5. Start processing requests asynchronously with Start-KrServer.

Folder layout (example)

Create a simple set of files to verify hosting:

examples/PowerShell/Tutorial/Assets/wwwroot/
  index.html
  css/site.css
  images/logo.png
  docs/readme.txt

Sample contents:

index.html

<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Kestrun Static Sample</title>
    <link rel="stylesheet" href="/assets/css/site.css" />
  </head>
  <body>
    <h1>Hello from static hosting</h1>
    <p>Served by Kestrun.</p>
  </body>
</html>

css/site.css

body { font-family: system-ui, Arial, sans-serif; margin: 2rem; }
h1 { color: #0d6efd; }

Try it

Start the server

. .\examples\PowerShell\Tutorial\3.1-Static-Routes.ps1

Browse / request files

curl http://127.0.0.1:5000/assets/index.html
curl http://127.0.0.1:5000/assets/css/site.css

Open in a browser: http://127.0.0.1:5000/assets/index.html

PowerShell requests

Invoke-WebRequest -Uri 'http://127.0.0.1:5000/assets/index.html' | Select-Object -ExpandProperty Content
Invoke-WebRequest -Uri 'http://127.0.0.1:5000/assets/css/site.css' | Select-Object -ExpandProperty Content

Customizing behavior

Add-KrStaticFilesService supports additional parameters (see cmdlet help) you can use to:

  • Change the request path prefix.
  • Point to multiple folders (register the service multiple times with different roots/prefixes).
  • Control caching headers (when supported) for performance.
  • Allow serving of unknown extensions with -ServeUnknownFileTypes (development / controlled scenarios). Prefer adding a proper content type mapping instead when possible.

Best practices

  • Always call Initialize-KrRoot when your script relies on relative paths; this avoids surprises when running from another directory.
  • Keep static assets outside script roots if you plan to containerize; mount or copy them during build.
  • Set far-future cache headers for versioned assets (e.g., /assets/app.123abc.js).
  • Consider a separate listener/port if you want to partition static + dynamic traffic (optional).
  • Avoid -ServeUnknownFileTypes in production unless absolutely required; limit exposed file types to reduce risk of unintentionally serving sensitive artifacts.

Troubleshooting

Symptom Cause Fix
404 Not Found for /assets file Path or filename mismatch Verify the physical file exists under the specified RootPath and spelling matches (case sensitivity depends on OS).
404 for all /assets requests Wrong relative path root Confirm Initialize-KrRoot points to a parent of Assets or use an absolute -RootPath.
Styles/images not loading in HTML Incorrect relative URLs Use absolute URLs beginning with /assets/... or correct relative pathing from the HTML file.
Changes not reflected Browser caching Hard refresh (Ctrl+F5) or add a cache-busting query string ?v=1.
Access denied errors File permissions Ensure read permissions for the process account on the asset files.

Cmdlet references


Next

Next: File Server & Directory Browsing
Skip ahead instead: Variable Routes