🐙 tako
Transports

Transports

Every Tako transport — HTTP, HTTP/3, WebSocket, WebTransport, SSE, gRPC, raw sockets, and PROXY protocol — with runtime and feature-flag support.

Tako runs the same Router across many transports. A single ServerConfig flows into every one of them, so header read timeouts, keep-alive, drain timeout, max connections, H2 caps, H3 caps, and the PROXY read timeout are all sourced from one struct. You pick which transport a listener serves at spawn time — the routing, middleware, and observability model does not change.

Transport matrix

TransportTokioCompioFeature flag
HTTP/1.1yesyesdefault
HTTP/2yesyeshttp2
HTTP/3 (QUIC)yesyeshttp3
TLS (rustls)yesyestls / compio-tls
WebSocketyesyesws
WebTransportyesyeswebtransport
SSEyesyessse
gRPC (unary and streaming)yesyesgrpc
Raw TCPyesyesdefault
Raw UDPyesyesudp
Unix socketsyesyesdefault (unix only)
PROXY protocol v1/v2yesyesproxy-protocol

Every transport runs on both runtimes: HTTP/2 over TLS, cleartext h2c, HTTP/3, WebTransport, raw TCP/UDP, Unix sockets, PROXY protocol, gRPC handlers, WebSocket, and SSE. Only the raw QUIC session helper behind webtransport is Tokio-only. See Runtimes and the feature reference.

How transports attach to a server

Use Server::builder() on Tokio or CompioServer::builder() on Compio. The try_spawn_* methods validate configuration before returning a handle; handle.result().await reports asynchronous startup and serving errors. shutdown(timeout).await stops acceptance and bounds the drain. Raw socket and per-thread servers keep their own helper functions.

use std::time::Duration;
use tako::{Server, ServerConfig};
use tako::router::Router;
use tokio::net::TcpListener;

#[tokio::main]
async fn main() -> Result<(), tako::types::BoxError> {
  let listener = TcpListener::bind("127.0.0.1:8080").await?;
  let mut router = Router::new();
  router.route(tako::Method::GET, "/", || async { "hi" });

  let server = Server::builder()
    .config(ServerConfig {
      drain_timeout: Duration::from_secs(30),
      max_connections: Some(10_000),
      ..ServerConfig::default()
    })
    .build();

  let handle = server.try_spawn_http(listener, router)?;
  tako::shutdown_signal().await?;
  handle.shutdown(Duration::from_secs(30)).await;
  Ok(())
}

The handle is runtime-agnostic — both Server (tokio) and CompioServer (compio) return the same ServerHandle type.

Per-transport pages

  • HTTP — HTTP/1.1, HTTP/2 cleartext (h2c), and HTTP/2 over TLS via ALPN.
  • HTTP/3 — HTTP/3 over QUIC on either runtime; TLS required.
  • WebSocket — RFC-6455 upgrade inside an HTTP handler, on both runtimes.
  • WebTransport — W3C WebTransport sessions on the HTTP/3 server, reachable from browsers; requires the webtransport feature.
  • SSE — Server-Sent Events; see the Streams primitives.
  • gRPC — unary and streaming RPCs with protobuf.
  • TCP / UDP / Unix — raw byte transports and Unix domain sockets.
  • PROXY protocol — v1/v2 header parsing behind an L4 load balancer.

WebSocket, SSE, and the HTTP handler

WebSocket and SSE live inside HTTP handlers. WebSocketUpgrade::new(req, handler) performs an HTTP/1.1 Upgrade; it works over plain HTTP/1.1 and TLS negotiated as HTTP/1.1. HTTP/2 Extended CONNECT is not implemented. tako::sse::Sse wraps a stream in a text/event-stream response and can use any supported HTTP transport.

Raw transports

spawn_tcp_raw / tako::server_tcp::serve_tcp and spawn_udp_raw / tako::server_udp::serve_udp skip the HTTP layer entirely. The handler closure receives each accepted stream (TCP) or datagram (UDP), so you can implement a custom line protocol, relay, or proxy. These do not use a Router. See TCP / UDP / Unix.

Last updated on

On this page