Status Code Pages Middleware

Status Code Pages middleware provides custom error pages for HTTP status codes between 400 and 599 that don’t have a response body. This is essential for providing user-friendly error pages instead of default browser error messages.

Overview

Kestrun provides several ways to configure status code pages:

  1. Default Status Code Pages - Basic error pages with minimal styling
  2. Custom Options - Configure with StatusCodePagesOptions for more control
  3. Custom Handler - Use a delegate function to handle status codes programmatically
  4. Script Handler - Use PowerShell scripts to generate custom error responses
  5. Content Format - Specify custom content type and body format with placeholders
  6. Redirects - Redirect error responses to specific URLs
  7. Re-execute - Re-execute the request pipeline with a different path

When to Use Status Code Pages

  • 404 Not Found - Provide custom “page not found” messages
  • 500 Internal Server Error - Show friendly error pages instead of stack traces
  • 403 Forbidden - Display access denied pages
  • 401 Unauthorized - Redirect to login pages or show authentication required messages

Routing Style Notes (Imperative vs Declarative)

Status Code Pages middleware runs after your endpoint executes, so it behaves the same whether you map routes imperatively (for example with Add-KrMapRoute) or declaratively (functions decorated with [OpenApiPath]).

Key points when using declarative attribute routing:

  • [OpenApiResponse(...)] documents the status code in OpenAPI, but it does not set the runtime response status.
  • To trigger Status Code Pages, your route must actually set a 4xx/5xx status code and typically leave the response body empty.
    • Use Write-KrStatusResponse -StatusCode 404 (or set Context.Response.StatusCode = 404 without writing a body).
    • If your route writes a body for the error response, Status Code Pages middleware will generally not replace it.

PowerShell Cmdlet

Use Enable-KrStatusCodePage to configure status code pages middleware with various options:

# Default status code pages
Enable-KrStatusCodePage

# With PowerShell script handler (custom body)
Enable-KrStatusCodePage -ScriptBlock {
    param($Context)
    $status = $Context.Response.StatusCode
    $Context.Response.ContentType = 'text/plain'
    $Context.Response.WriteAsync("Custom handler status: $status") | Out-Null
}

# With LanguageOptions (advanced: cross-language code)
$lo = [Kestrun.Hosting.Options.LanguageOptions]::new()
$lo.Language = [Kestrun.Scripting.ScriptLanguage]::PowerShell
$lo.Code = @'
param($Context)
$Context.Response.ContentType = "text/plain"
$Context.Response.WriteAsync("Handled by LanguageOptions") | Out-Null
'@
Enable-KrStatusCodePage -LanguageOptions $lo

# With content format
Enable-KrStatusCodePage -ContentType "text/html" -BodyFormat $htmlTemplate

# With redirects
Enable-KrStatusCodePage -LocationFormat "/error/{0}"

# With re-execution
Enable-KrStatusCodePage -PathFormat "/errors/{0}" -QueryFormat "originalPath={0}"

Sample Scripts

The following examples demonstrate different approaches to handling status codes:

Each example builds on the hello-world template and shows how to trigger and handle different status codes.

Best Practices

  1. Always handle 404 errors - Provide meaningful “not found” pages
  2. Secure error messages - Don’t expose sensitive information in error pages
  3. Consistent styling - Match your application’s design
  4. Logging - Log errors while showing friendly messages to users
  5. Testing - Test error pages with various status codes

Advanced Configuration

Custom Error Pages with External Files

For better maintainability, separate HTML templates from PowerShell code:

# Load HTML template from external file
$htmlTemplatePath = Join-Path $PSScriptRoot "Assets\wwwroot\statuscodepages\error-template.html"
$htmlTemplate = Get-Content -Path $htmlTemplatePath -Raw

# Use with content format
Enable-KrStatusCodePage -ContentType "text/html; charset=utf-8" -BodyFormat $htmlTemplate

Error Page Hierarchies

Organize error pages by status code families:

  • 4xx Client Errors - User-facing friendly messages
  • 5xx Server Errors - Technical support contact information
  • Custom Status Codes - Application-specific error handling

Integration with Logging

Combine status code pages with structured logging:

$handler = {
    param($context)
    $statusCode = $context.HttpContext.Response.StatusCode

    # Log the error with context
    Write-KrLog -Level Error -Message "Status code $statusCode" -Properties @{
        Path = $context.HttpContext.Request.Path
        UserAgent = $context.HttpContext.Request.Headers["User-Agent"]
    }

    # Generate custom response
    # ... error page logic
}

Enable-KrStatusCodePage -ScriptBlock $handler

Return to the Guides index.