DocsGuidesWebSockets & SSE

WebSockets & SSE

Not hardened yet (M4)

Plain HTTP request/response is what ngstone has actually been built and tested for. WebSocket and SSE traffic is not yet specifically tested or hardened — it may work today as a side effect of the stdlib reverse proxy's default behavior, but don't rely on it in production until M4 lands.

Long-lived connections aren't meant to be a special case in ngstone's design — they'd ride the same per-request yamux stream as any other HTTP exchange, for as long as they stay open.

WebSocket passthrough#

Both the edge and the agent use Go's stdlib httputil.ReverseProxy, which handles Connection: Upgrade on its own — hijacking the connection, completing the 101handshake, and copying bytes bidirectionally for the rest of the socket's life, over the same yamux stream that was opened for the original upgrade request. That's the mechanism in place today; it just hasn't been specifically exercised or hardened yet (see the callout above), so treat it as untested rather than guaranteed.

WebSocket over HTTP/2#

Not enabled

WS-over-h2 (RFC 8441 extended CONNECT) is not enabled on the edge. Browsers already fall back to HTTP/1.1 for WebSocket upgrades automatically, so this is a non-issue in practice — just don't expect an h2 WebSocket frame in the wild.

Server-Sent Events#

SSE is plain HTTP streaming, not an upgrade, and both proxies set FlushInterval: -1, which flushes bytes to the client as soon as they arrive instead of batching them. That part rides the same code path as ordinary HTTP responses, so it's on firmer ground than WebSockets — but it hasn't been separately load-tested for long-lived streams either, which is why it's grouped under the same M4 milestone.

How they appear in the inspector#

The request inspector already understands WebSockets: an upgrade is finalized in the inspector at 101 time, not at close, so a long-lived connection shows up in the request list the instant it connects instead of staying invisible until the socket eventually closes. Rows for an open socket show WSin the method column and live byte counts in both directions in place of a duration. This inspector behavior is solid; it's the broader WebSocket/SSE hardening above (M4) that's still outstanding.