Commits
Tarun Sukhani authored f38592be60d
feat(websocket): WebSocket over HTTP/3 via Extended CONNECT (PF-158) Implements RFC 9220 so a WebSocket can be established on an h3 request stream with Extended CONNECT, reusing PF-157's bridge. HTTP/3 has no Upgrade mechanism, so this is what makes WebSocket possible at all over the QUIC path rather than merely cheaper. Http3ServerInitializer advertises the h3 connect-protocol setting (0x8), built from Http3Settings.defaultSettings() so the QPACK and field-section defaults Netty would otherwise supply are still advertised, and passing disableQpackDynamicTable=true to match what the one-argument Http3ServerConnectionHandler constructor used before. Http3ExtendedConnectHandler mirrors its h2 counterpart, and two things differ in our favour. Netty implements RFC 9220 validation directly: Http3HeadersSink enforces an exact METHOD|SCHEME|AUTHORITY|PATH|PROTOCOL pseudo-header mask for Extended CONNECT, so malformed requests never reach us — HTTP/2 has no such check anywhere. And Http3Headers exposes a typed protocol() accessor that Http2Headers lacks. The half-close signal differs too: on h2 it rides the DATA frame's END_STREAM flag, on h3 it is a ChannelInputShutdownEvent. Both close the stream so PlayHandler.channelInactive releases the controller's Inbound rather than leaving a virtual thread parked in nextEvent() forever. Keeping the QUIC request stream open indefinitely is legal: Http3RequestStreamValidationHandler only enforces content-length consistency (absent here) and the encode-state validator accepts one final HEADERS followed by unbounded DATA. Tested by a hand-rolled Netty h3 client following Http3FunctionalTest's shape, minus the SHUTDOWN_OUTPUT that test uses. No regression on h2 or the HTTP/1.1 classic and fallback paths. Docs: new "WebSockets over HTTP/2 and HTTP/3" section in httpserver.textile, including the caveat that Firefox uses Extended CONNECT for new WebSocket() over h2 while Chrome does not and falls back to an HTTP/1.1 wss:// connection. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>