Mixed HTTP Protocols

Expose the same application over multiple listeners each constrained to a specific HTTP protocol version (HTTP/1.1, HTTP/2, HTTP/3), plus an example of a combined protocol listener.

HTTP/3 requires OS + .NET support (QUIC). If unavailable the listener will fail or downgrade.

Full source

File: pwsh/tutorial/examples/7.6-Mixed-HttpProtocols.ps1

<#
    Sample: Mixed HTTP Protocol Versions
    Purpose: Demonstrate configuring multiple listeners each with a different HTTP protocol set (HTTP/1.1, HTTP/2, HTTP/3*) plus a combined HTTP/1.1+HTTP/2 listener.
    File:    7.6-Mixed-HttpProtocols.ps1
    Notes:   HTTP/3 requires platform & runtime support + QUIC enabled. If HTTP/3 is not available, that listener may fail to bind.
#>
param(
    [int]$Port = 5000,
    [IPAddress]$IPAddress = [IPAddress]::Loopback
)
# 1. Logging (console)
New-KrLogger | Add-KrSinkConsole | Register-KrLogger -Name 'console' -SetAsDefault | Out-Null

# 2. Create server
New-KrServer -Name 'Endpoints Mixed Protocols'

# For HTTPS listeners, create a self-signed cert (or load from store/file as needed)
$cert = New-KrSelfSignedCertificate -DnsNames localhost, 127.0.0.1 -Exportable -ValidDays 30

# 3. Listeners with explicit protocol selections
#    - 5001: HTTP/1.1 only
Add-KrEndpoint -Port $Port -IPAddress $IPAddress -Protocols ([Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols]::Http1) -X509Certificate $cert
#    - 5002: HTTP/2 only (no HTTP/1.1)
Add-KrEndpoint -Port ($Port + 1) -IPAddress $IPAddress -Protocols ([Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols]::Http2) -X509Certificate $cert
#    - 5003: HTTP/3 only (QUIC) Requires OS + runtime support; may need environment variable ASPNETCORE_URLS / alt config.
Add-KrEndpoint -Port ($Port + 2) -IPAddress $IPAddress -Protocols ([Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols]::Http3) -X509Certificate $cert
#    - 5004: Combined HTTP/1.1 + HTTP/2 (single listener negotiating via ALPN when TLS used; here plain for demo)
Add-KrEndpoint -Port ($Port + 3) -IPAddress $IPAddress -Protocols ([Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols]::Http1AndHttp2) -X509Certificate $cert


# 5. Enable configuration
Enable-KrConfiguration

# 6. Single route served by all listeners
Add-KrMapRoute -Verbs Get -Pattern '/version' -ScriptBlock {
    $proto = $Context.HttpContext.Request.Protocol
    Write-KrTextResponse -InputObject "Hello via $proto" -ContentType 'text/plain'
}

# 7. Start server (Ctrl+C to stop)
Start-KrServer -CloseLogsOnExit

Step-by-step

  1. Create server & logger.
  2. Add four listeners with explicit -Protocols values: Http1, Http2, Http3, and Http1AndHttp2 (combined).
  3. Enable configuration.
  4. Map /version route returning negotiated protocol.
  5. Start server.

Try it

With Curl:

curl -v --http1.1 -k https://127.0.0.1:5001/version
curl -v --http2-prior-knowledge -k https://127.0.0.1:5002/version
# HTTP/3 (requires curl built with HTTP/3 + QUIC):
curl -v --http3 -k https://127.0.0.1:5003/version
# Combined (shows negotiated protocol or HTTP/1.1 without TLS):
curl -v -k https://127.0.0.1:5004/version

With Invoke-WebRequest:

# HTTP/1.1
Invoke-WebRequest -Uri "https://127.0.0.1:5001/version" -HttpVersion 1.1 -SkipCertificateCheck -Verbose

# HTTP/2 (prior knowledge)
Invoke-WebRequest -Uri "https://127.0.0.1:5002/version" -HttpVersion 2.0 -SkipCertificateCheck -Verbose

# HTTP/3 (requires .NET + OS support for QUIC)
Invoke-WebRequest -Uri "https://127.0.0.1:5003/version" -HttpVersion 3.0 -SkipCertificateCheck -Verbose

# Combined (let it negotiate, default is 1.1 without TLS)
Invoke-WebRequest -Uri "https://127.0.0.1:5004/version" -SkipCertificateCheck -Verbose

Each response prints: Hello via HTTP/<version>.

Enum values

[Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols] supports: Http1, Http2, Http3, and flag combinations (Http1AndHttp2, Http1AndHttp3, Http2AndHttp3, Http1AndHttp2AndHttp3). You can also combine flags manually:

$all = [Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols]::Http1 -bor \
  [Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols]::Http2 -bor \
  [Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols]::Http3
Add-KrEndpoint -Port 5010 -IPAddress ([IPAddress]::Loopback) -Protocols $all

HTTP/2 generally requires TLS in browsers; HTTP/3 always requires QUIC + TLS.

References

Troubleshooting

Symptom Cause Fix
HTTP/3 listener fails QUIC not supported Remove HTTP/3 line or upgrade OS/runtime
All versions say HTTP/1.1 H2/H3 not negotiated Use proper curl flags or ALPN support
Port in use Already bound Change port numbers

See also: Multiple Listeners · HTTPS


Previous / Next