SSE

Stream real-time server events to browsers using Server-Sent Events (SSE).

Full source

File: pwsh/tutorial/examples/15.9-Sse.ps1

<#
    Create an SSE demo server with Kestrun in PowerShell.
    FileName: 15.9-Sse.ps1

    This demo focuses on the per-connection SSE helpers:
    - Start-KrSseResponse
    - Write-KrSseEvent
#>
param(
    [int]$Port = 5000,
    [IPAddress]$IPAddress = [IPAddress]::Loopback
)

if (-not (Get-Module Kestrun)) { Import-Module Kestrun }

# Initialize Kestrun root directory
Initialize-KrRoot -Path $PSScriptRoot

## 1. Logging
New-KrLogger |
    Set-KrLoggerLevel -Value Debug |
    Add-KrSinkConsole | Register-KrLogger -Name 'SseDemo' -SetAsDefault

## 2. Create Server
New-KrServer -Name 'Kestrun SSE Demo'

## 3. Configure Listener
Add-KrEndpoint -Port $Port -IPAddress $IPAddress

## 4. Enable Configuration
Enable-KrConfiguration

## 5. Routes
# Simple home page with an EventSource client
Add-KrHtmlTemplateRoute -Pattern '/' -HtmlTemplatePath 'Assets/wwwroot/sse.html'

# SSE stream endpoint (per connection)
Add-KrMapRoute -Verbs Get -Pattern '/sse' {
    $count = Get-KrRequestQuery -Name 'count' -AsInt
    if ($count -le 0) { $count = 30 }

    $intervalMs = Get-KrRequestQuery -Name 'intervalMs' -AsInt
    if ($intervalMs -le 0) { $intervalMs = 1000 }

    Start-KrSseResponse

    $connected = @{
        message = 'Connected to Kestrun SSE stream'
        serverTime = (Get-Date)
        count = $count
        intervalMs = $intervalMs
    } | ConvertTo-Json -Compress

    Write-KrSseEvent -Event 'connected' -Data $connected -retryMs 2000

    for ($i = 1; $i -le $count; $i++) {
        $payload = @{
            i = $i
            total = $count
            timestamp = (Get-Date)
        } | ConvertTo-Json -Compress

        try {
            Write-KrSseEvent -Event 'tick' -Data $payload -id "$i"
        } catch {
            # Most common cause: client disconnected.
            Write-KrLog -Level Debug -Message 'SSE write failed (client disconnected?)' -Exception $_
            break
        }

        Start-Sleep -Milliseconds $intervalMs
    }

    $complete = @{
        message = 'Stream complete'
        total = $count
        serverTime = (Get-Date)
    } | ConvertTo-Json -Compress

    try {
        Write-KrSseEvent -Event 'complete' -Data $complete
    } catch {
        Write-KrLog -Level Debug -Message 'SSE write failed on completion (client disconnected?)' -Exception $_
        # Client may have disconnected; ignore.
    }
}

## 6. Start Server

Write-Host '🟢 Kestrun SSE Demo Server Started' -ForegroundColor Green
Write-Host "📍 Navigate to http://localhost:$Port to see the demo" -ForegroundColor Cyan
Write-Host "📡 SSE stream endpoint: http://localhost:$Port/sse" -ForegroundColor Cyan

Start-KrServer -CloseLogsOnExit

Step-by-step

  1. Logging: Register a console logger as default.
  2. Server: Create a server and listener (IP + port).
  3. Configuration: Enable configuration so routes/middleware are materialized.
  4. Home page: Serve an HTML page with an EventSource client.
  5. Input: Read count and intervalMs from query parameters.
  6. SSE response: Start the SSE response with Start-KrSseResponse.
  7. Events: Emit connected, tick, and complete SSE events using Write-KrSseEvent.
  8. Run: Start the server and connect from a browser or curl.

Try it

Start the server:

pwsh .\docs\_includes\examples\pwsh\15.9-Sse.ps1

Stream a short SSE response (closes after count events):

curl -N "http://127.0.0.1:5000/sse?count=3&intervalMs=100"

Open the demo UI:

Start-Process http://127.0.0.1:5000/

Troubleshooting

Symptom Cause Fix
Browser reconnects repeatedly Stream closes (expected) This sample intentionally ends the stream after count events; close the EventSource on onerror.
No events arrive Proxy buffering Ensure you use Start-KrSseResponse and avoid middleware that buffers responses.
curl hangs Stream is long-running Use small count values when testing from CLI.

References


Previous / Next

Previous: CORS Next: SSE Broadcast