tokio-tungstenite
Asynchronous, Tokio-native WebSocket streams built on tungstenite
Repository Health
Technical Analysis
tokio-tungstenite wraps the synchronous tungstenite WebSocket library in a Tokio-friendly async API, exposing every connection as a WebSocketStream<S> that implements the standard futures Stream and Sink traits. That means a WebSocket connection behaves like any other async stream of messages in the Tokio ecosystem — compatible with select!, combinators from futures-util, and tokio::spawn’d tasks — without the caller ever touching a blocking read or write.
The crate covers both sides of the protocol: connect_async and client_async for establishing outbound client connections, and accept_async / accept_hdr_async for accepting inbound server connections, with optional TLS (native-tls or rustls) gated behind Cargo feature flags so plaintext-only deployments don’t pull in a TLS stack at all.
What You Get
connect_async/connect_async_with_config— one-call client connections that resolve host/port from the URL, open the TCP socket, and complete the WebSocket handshakeaccept_async/accept_hdr_async— server-side handshake acceptance, with the_hdrvariant exposing a callback to inspect or add HTTP headers during the upgradeWebSocketStream<S>implementingStream<Item = Result<Message, Error>>andSink<Message>, so messages can be read and written with ordinaryfuturescombinators- Pluggable TLS via
native-tls,rustls-tls-native-roots, orrustls-tls-webpki-rootsCargo features, unified behind aMaybeTlsStreamenum and aConnectortype for custom TLS configuration - Generic support for any
AsyncRead + AsyncWritetransport, not justTcpStream— useful for testing over in-memory duplex streams or layering on custom transports
Common Use Cases
- Real-time chat, notification, or collaborative-editing backends where a Tokio-based server needs to push and receive messages over long-lived connections
- Async clients that subscribe to a WebSocket API (exchange price feeds, streaming logs, live dashboards) and fold incoming messages into an application’s event loop
- WebSocket proxies or gateways that terminate TLS and relay frames between an upstream and downstream socket using the same
Stream/Sinkabstraction on both sides - Load and protocol-conformance testing against the Autobahn Test Suite, which the crate ships dedicated client/server examples for
Under The Hood
Architecture: The crate layers cleanly around one core abstraction: compat::AllowStd<S>, a wrapper that lets the synchronous tungstenite::WebSocket (which expects std::io::Read/Write) run on top of an async AsyncRead/AsyncWrite transport. AllowStd holds two WakerProxy instances (one for reads, one for writes) so the Stream side and Sink side of a WebSocketStream can each register their own task waker without clobbering the other’s — solving the classic problem where a single stored waker only remembers the most recent poller. handshake.rs drives the handshake as a hand-rolled Future (StartedHandshakeFuture / MidHandshake) that repeatedly calls into tungstenite’s synchronous handshake state machine until it’s Interrupted (would-block, poll again) or done. connect.rs and tls.rs layer TCP connection and optional TLS negotiation (via native-tls or rustls, unified as stream::MaybeTlsStream) on top of that. lib.rs then exposes WebSocketStream<S> implementing futures_util::Stream and Sink<Message>, translating tungstenite’s WouldBlock I/O errors into Poll::Pending.
Tech Stack: Pure Rust (96% of the codebase), edition 2018, MSRV 1.85. Core dependencies are tungstenite (the underlying sync WebSocket protocol implementation, pinned to the same 0.30.0 version), tokio (only the io-util feature by default — net is pulled in only when the connect feature is enabled), futures-util (sink + std features), and log. TLS is entirely optional and additive: native-tls/tokio-native-tls, or rustls/tokio-rustls/rustls-native-certs/webpki-roots, selected via Cargo features so a plaintext-only build carries none of that weight.
Code Quality: The public API is annotated with #![deny(missing_docs, unused_must_use, unused_mut, unused_imports, unused_import_braces)], so every exported item carries a doc comment, and the crate is disciplined about warning-free code. Integration tests are thin — tests/handshakes.rs (25 lines, one round-trip handshake test) and tests/communication.rs (106 lines) — with no dedicated unit tests for the TLS wrapping paths or WebSocketConfig edge cases; confidence there instead comes from the Autobahn Test Suite examples and tungstenite’s own test suite. No unsafe code is used in the crate’s own source.
API Design: The ergonomics lean on Rust’s trait system rather than bespoke types: connect_async(url) accepts anything implementing IntoClientRequest (a plain &str, a http::Request, etc.), and the returned WebSocketStream is immediately usable with .split(), StreamExt::next(), and SinkExt::send() from futures-util — no bespoke read/write methods to learn. Feature flags keep opt-in surface area (TLS backends, connection helpers) cleanly separated from the always-on protocol/stream plumbing, and the crate re-exports tungstenite directly so callers reach protocol-level types (Message, CloseFrame, error types) without a second dependency declaration.
Used by 25 apps in this directory
OpenPencil
AI Design Tools
An open-source, AI-native vector design tool with concurrent agent teams, design-as-code, a built-in MCP server, and multi-model intelligence — a distinct project from the similarly-named Figma-file-reading "open-pencil" editor.
Rivet
AI Agents · Developer Tools
Stateful actors as a primitive for AI agents, real-time collaboration, and durable execution — with in-memory state, WebSockets, queues, and scheduling built in.
Stalwart
Collaboration
All-in-one secure mail and collaboration server covering IMAP, JMAP, SMTP, CalDAV, CardDAV, and WebDAV in a single memory-safe Rust binary.
Svix
Automation · Developer Tools
Open source, self-hostable webhook infrastructure that handles delivery, retries, HMAC signing, and multi-tenant event management so you never have to build a webhooks system from scratch.
Tabby
AI Code Assistants
Self-hosted AI coding assistant — run GitHub Copilot-grade code completion on your own hardware with no cloud dependency.
Temps
Analytics · Devops · Monitoring
A self-hosted Rust PaaS that replaces Vercel, Sentry, PostHog, Pingdom, Resend, and E2B with one binary — plus 440+ CLI operations agents like Claude Code can drive directly.
Vibe Kanban
AI Agents · AI Code Assistants · Project Management
A kanban board for planning work and dispatching Claude Code, Codex, Gemini CLI, and eight other coding agents into isolated git worktrees, then reviewing and merging their diffs from one UI.