Skip to content

feat: WebSocket upgrade and text echo on http::server#21

Merged
ruoka merged 7 commits into
masterfrom
feat/websocket
Jul 19, 2026
Merged

feat: WebSocket upgrade and text echo on http::server#21
ruoka merged 7 commits into
masterfrom
feat/websocket

Conversation

@ruoka

@ruoka ruoka commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • RFC 6455 frame encode/decode (net:websocket_frame) and accept-key + session loop (net:websocket)
  • http::server::ws(path).ws(handler) registration; GET + Upgrade: websocket101 then text session (ping/pong/close/echo)
  • Upgrade is connection handoff in the server, not a callback_with_headers middleware

Test plan

  • ./tools/CB.sh debug build --jsonl=failures
  • NET_DISABLE_NETWORK_TESTS=0 ./tools/CB.sh debug test --jsonl=failures --tags='\[net\]' (455/455)
  • RFC accept-key golden + masked frame round-trip + loopback echo

Made with Cursor

@cursor

cursor Bot commented Jul 18, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

ruoka and others added 7 commits July 19, 2026 15:22
Add RFC 6455 framing, Sec-WebSocket-Accept, and server.ws(path).ws(handler)
registration. Upgrade takes over the connection after 101; middleware stays
HTTP-phase only. Includes unit and loopback echo tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add unit tests exercising previously-uncovered paths:
- unmasked server frame round-trip
- 64-bit extended length frames
- read_frame rejection of oversized (>1 MiB) and truncated payloads
- run_text_session text echo, nullopt suppression, ping->pong, pong-ignore,
  and close handshake termination

Uses an in-memory duplex stream helper so run_text_session is exercised
without a socket, so the new cases run even when network tests are disabled.

Co-authored-by: Kaius  Ruokonen <ruoka@users.noreply.github.com>
Per RFC 6455 5.1, client-to-server frames must be masked. run_text_session
now rejects any unmasked incoming frame with a 1002 (protocol error) close and
ends the session. Adds close status-code constants and a make_close_frame
overload that carries a 2-byte big-endian code.

Co-authored-by: Kaius  Ruokonen <ruoka@users.noreply.github.com>
Co-authored-by: Kaius  Ruokonen <ruoka@users.noreply.github.com>
Fail closed with close codes: no fragmentation/binary (1003), invalid
UTF-8 (1007), oversized payloads (1009), RSV/control violations (1002).
UTF-8 validation is self-contained in net (no xson dependency).

Co-authored-by: Cursor <cursoragent@cursor.com>
Provide a minimal text client matching the server spike: HTTP upgrade,
masked outbound frames, automatic ping/pong, and close handshake.

Co-authored-by: Cursor <cursoragent@cursor.com>
Name the optional outbound payload and drop trailing return types on
handler lambdas in favor of return text_reply{…}.

Co-authored-by: Cursor <cursoragent@cursor.com>
@ruoka
ruoka merged commit 8b7582f into master Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants