tako-rs 1.1.1

Multi-transport Rust framework for modern network services.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
#![cfg_attr(docsrs, feature(doc_cfg))]

//! A multi-transport Rust framework for modern network services.
//!
//! Tako is built for services that go beyond plain HTTP. It gives you one
//! cohesive model for routing, extraction, middleware, streaming, observability,
//! and graceful shutdown across several protocols and transport layers.
//!
//! # Why Tako
//! - One application can expose HTTP APIs, realtime channels, and raw transports
//!   without switching frameworks.
//! - The same ergonomic handler and extractor model applies across higher-level
//!   web routes and lower-level network services.
//! - Platform primitives such as middleware, queues, signals, streaming, metrics,
//!   and file serving are part of the framework story.
//! - You can stay on the default `tokio` runtime or opt into `compio` where it
//!   is a better fit.
//!
//! # High-level features
//! - Multi-transport support: HTTP/1.1, HTTP/2, HTTP/3, WebSocket, SSE, gRPC,
//!   TCP, UDP, Unix sockets, PROXY protocol, and WebTransport
//! - Dual runtime support with `tokio` by default and optional `compio`
//! - Macro-free routing with dynamic path params and TSR support
//! - Type-safe handlers with extractor-based arguments
//! - Simple `Responder` trait to return strings, tuples, or full responses
//! - Middleware pipeline plus optional plugins for CORS, compression, rate
//!   limiting, and metrics
//! - Streaming bodies, file serving, range requests, and SSE helpers
//! - Built-in background queue and in-process signals for application workflows
//! - Optional GraphQL support, GraphiQL UI, and OpenAPI integrations
//!
//! # Runtime support
//! - `tokio` is the default runtime and powers the standard server path
//! - `compio` is available behind feature flags for teams that want an
//!   alternative async runtime model
//! - `hyper` 1.x remains the core HTTP engine for the default runtime path
//!
//! # Best fit
//! Tako is a strong fit when your service needs more than REST:
//! - HTTP APIs plus WebSockets, SSE, gRPC, or QUIC-based transports
//! - Realtime coordination with built-in signals and queue primitives
//! - Protocol gateways, telemetry collectors, internal platforms, or edge-facing
//!   services
//!
//! # Quickstart
//!
//! ```rust
//! use tako::{Method, router::Router, responder::Responder, types::Request};
//!
//! async fn hello(_: Request) -> impl Responder { "Hello, World!" }
//!
//! let mut router = Router::new();
//! router.route(Method::GET, "/", hello);
//! ```
//!
//! # Key concepts
//! - [router::Router] manages routes, middleware and dispatch.
//! - [extractors] parse request data (headers, params, JSON, forms, etc.).
//! - [responder::Responder] converts return values into HTTP responses.
//! - [middleware] composes cross-cutting concerns.
//!
//! - Static file serving (module `static`) and [file_stream] provide static and streaming file responses.
//! - [ws] and [sse] enable real-time communication.
//! - [queue] and [signals] provide built-in application coordination primitives.
//! - [plugins] add CORS, compression, and rate limiting (feature: `plugins`).
//! - [graphql] and [graphiql] add GraphQL support (feature: `async-graphql` / `graphiql`).
//!
//! # Feature flags
//! - `client` — outbound HTTP clients over TCP/TLS
//! - `compio` — alternate runtime support
//! - `compio-tls` / `compio-ws` — TLS and WebSocket support on compio
//! - `file-stream` — file streaming utilities
//! - `http2` — enable ALPN h2 in TLS server
//! - `http3` — HTTP/3 over QUIC
//! - `jemalloc` — use jemalloc as global allocator
//! - `multipart` — multipart form-data extractors
//! - `plugins` — CORS, compression, rate limiting
//! - `protobuf` — protobuf extractors (prost)
//! - `simd` — SIMD JSON extractor (simd-json)
//! - `signals` — in-process pub/sub and RPC-style signaling
//! - `tls` — TLS server (rustls)
//! - `tako-tracing` — structured tracing subscriber
//! - `utoipa` / `vespera` — OpenAPI integrations
//! - `webtransport` — QUIC-based WebTransport sessions
//! - `zero-copy-extractors` — zero-copy extraction helpers
//! - `zstd` — Zstandard compression option within plugins::compression

use std::io::ErrorKind;
use std::io::Write;
use std::io::{self};
use std::net::SocketAddr;
use std::str::FromStr;

/// HTTP request and response body handling utilities.
pub mod body;

/// HTTP client implementation for making outbound requests.
#[cfg(all(feature = "client", not(feature = "compio")))]
#[cfg_attr(docsrs, doc(cfg(feature = "client")))]
pub mod client;

/// Configuration loading from environment variables.
pub mod config;

/// Request data extraction utilities for parsing query params, JSON, and more.
pub mod extractors;

/// File streaming utilities for serving files.
#[cfg(feature = "file-stream")]
#[cfg_attr(docsrs, doc(cfg(feature = "file-stream")))]
pub mod file_stream;

/// Request handler traits and implementations.
mod handler;

/// Middleware for processing requests and responses in a pipeline.
pub mod middleware;

/// Plugin system for extending framework functionality.
#[cfg(feature = "plugins")]
#[cfg_attr(docsrs, doc(cfg(feature = "plugins")))]
pub mod plugins;

/// Response generation utilities and traits.
pub mod responder;

/// Redirection utilities for handling HTTP redirects.
pub mod redirect;

/// Route definition and matching logic.
mod route;

/// Request routing and dispatch functionality.
pub mod router;

/// HTTP server implementation and configuration.
#[cfg(not(feature = "compio"))]
mod server;

/// Server-Sent Events (SSE) support for real-time communication.
pub mod sse;

/// In-memory background job queue with retry, delayed jobs, and dead letter support.
pub mod queue;

/// Application state management and dependency injection.
pub mod state;

#[cfg(feature = "signals")]
/// In-process signal arbiter for custom events.
pub mod signals;

/// Static file serving utilities.
pub mod r#static;

/// Distributed tracing integration for observability.
#[cfg(feature = "tako-tracing")]
#[cfg_attr(docsrs, doc(cfg(feature = "tako-tracing")))]
pub mod tracing;

/// Core type definitions used throughout the framework.
pub mod types;

/// WebSocket connection handling and message processing.
#[cfg(not(feature = "compio"))]
pub mod ws;

/// WebSocket connection handling for compio runtime.
#[cfg(feature = "compio-ws")]
#[cfg_attr(docsrs, doc(cfg(feature = "compio-ws")))]
pub mod ws_compio;

/// GraphQL support (request extractors, responses, and subscriptions).
#[cfg(feature = "async-graphql")]
#[cfg_attr(docsrs, doc(cfg(feature = "async-graphql")))]
pub mod graphql;

/// GraphiQL UI helpers.
#[cfg(feature = "graphiql")]
#[cfg_attr(docsrs, doc(cfg(feature = "graphiql")))]
pub mod graphiql;

/// OpenAPI documentation generation integrations (utoipa, vespera).
#[cfg(any(feature = "utoipa", feature = "vespera"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "utoipa", feature = "vespera"))))]
pub mod openapi;

#[cfg(feature = "zero-copy-extractors")]
#[cfg_attr(docsrs, doc(cfg(feature = "zero-copy-extractors")))]
pub mod zero_copy_extractors;

pub use bytes::Bytes;
pub use http::Method;
pub use http::StatusCode;
pub use http::header;
pub use http_body_util::Full;
pub use responder::NOT_FOUND;
/// Starts the HTTP server with the given listener and router.
///
/// This is the main entry point for starting a Tako web server. The function takes
/// ownership of a TCP listener and router, then serves incoming connections until
/// the server is shut down.
///
/// # Examples
///
/// ```rust,no_run
/// use tako::{serve, router::Router};
/// use tokio::net::TcpListener;
///
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
/// let listener = TcpListener::bind("127.0.0.1:8080").await?;
/// let router = Router::new();
/// serve(listener, router).await;
/// # Ok(())
/// # }
/// ```
#[cfg(not(feature = "compio"))]
pub use server::serve;
#[cfg(not(feature = "compio"))]
pub use server::serve_with_shutdown;
#[cfg(feature = "compio")]
pub use server_compio::serve;
#[cfg(feature = "compio")]
pub use server_compio::serve_with_shutdown;

/// Bind a TCP listener for `addr`, asking interactively to increment the port
/// if it is already in use.
///
/// This helper is primarily intended for local development and example binaries.
/// It will keep proposing the next port number until a free one is found or
/// the user declines.
///
/// # Errors
///
/// Returns an error if:
/// - The provided address string is not a valid socket address.
/// - The port is already in use and the user declines to try another port.
/// - A non-recoverable I/O error occurs during binding.
#[cfg(not(feature = "compio"))]
pub async fn bind_with_port_fallback(addr: &str) -> io::Result<tokio::net::TcpListener> {
  let mut socket_addr =
    SocketAddr::from_str(addr).map_err(|e| io::Error::new(ErrorKind::InvalidInput, e))?;
  let start_port = socket_addr.port();

  loop {
    let addr_str = socket_addr.to_string();
    match tokio::net::TcpListener::bind(&addr_str).await {
      Ok(listener) => {
        if socket_addr.port() != start_port {
          println!(
            "Port {} was in use, starting on {} instead",
            start_port,
            socket_addr.port()
          );
        }
        return Ok(listener);
      }
      Err(err) if err.kind() == ErrorKind::AddrInUse => {
        let next_port = socket_addr.port().saturating_add(1);
        if !ask_to_use_next_port(socket_addr.port(), next_port)? {
          return Err(err);
        }
        socket_addr.set_port(next_port);
      }
      Err(err) => return Err(err),
    }
  }
}

/// Bind a TCP listener for `addr`, asking interactively to increment the port
/// if it is already in use (compio version).
///
/// # Errors
///
/// Returns an error if:
/// - The provided address string is not a valid socket address.
/// - The port is already in use and the user declines to try another port.
/// - A non-recoverable I/O error occurs during binding.
#[cfg(feature = "compio")]
pub async fn bind_with_port_fallback(addr: &str) -> io::Result<compio::net::TcpListener> {
  let mut socket_addr =
    SocketAddr::from_str(addr).map_err(|e| io::Error::new(ErrorKind::InvalidInput, e))?;
  let start_port = socket_addr.port();

  loop {
    let addr_str = socket_addr.to_string();
    match compio::net::TcpListener::bind(&addr_str).await {
      Ok(listener) => {
        if socket_addr.port() != start_port {
          println!(
            "Port {} was in use, starting on {} instead",
            start_port,
            socket_addr.port()
          );
        }
        return Ok(listener);
      }
      Err(err) if err.kind() == ErrorKind::AddrInUse => {
        let next_port = socket_addr.port().saturating_add(1);
        if !ask_to_use_next_port(socket_addr.port(), next_port)? {
          return Err(err);
        }
        socket_addr.set_port(next_port);
      }
      Err(err) => return Err(err),
    }
  }
}

fn ask_to_use_next_port(current: u16, next: u16) -> io::Result<bool> {
  loop {
    print!(
      "Port {} is already in use. Start on {} instead? [Y/n]: ",
      current, next
    );
    io::stdout().flush()?;

    let mut input = String::new();
    io::stdin().read_line(&mut input)?;
    let trimmed = input.trim();

    if trimmed.is_empty()
      || trimmed.eq_ignore_ascii_case("y")
      || trimmed.eq_ignore_ascii_case("yes")
    {
      return Ok(true);
    }

    if trimmed.eq_ignore_ascii_case("n") || trimmed.eq_ignore_ascii_case("no") {
      return Ok(false);
    }

    println!("Please answer 'y' or 'n'.");
  }
}

/// TLS/SSL server implementation for secure connections.
#[cfg(all(not(feature = "compio-tls"), feature = "tls"))]
#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
pub mod server_tls;

/// Compio server implementation for efficient I/O operations.
#[cfg(feature = "compio")]
#[cfg_attr(docsrs, doc(cfg(feature = "compio")))]
pub mod server_compio;

#[cfg(feature = "compio-tls")]
#[cfg_attr(docsrs, doc(cfg(feature = "compio")))]
pub mod server_tls_compio;

/// HTTP/3 server implementation using QUIC transport.
#[cfg(all(feature = "http3", not(feature = "compio")))]
#[cfg_attr(docsrs, doc(cfg(feature = "http3")))]
pub mod server_h3;

/// Raw TCP server for handling arbitrary TCP connections.
pub mod server_tcp;

/// UDP datagram server for handling raw UDP packets.
pub mod server_udp;

/// Unix Domain Socket server for local IPC and reverse proxy communication.
#[cfg(all(unix, not(feature = "compio")))]
pub mod server_unix;

/// PROXY protocol v1/v2 parser for load balancer integration.
#[cfg(not(feature = "compio"))]
pub mod proxy_protocol;

/// gRPC support for unary RPCs with protobuf serialization.
#[cfg(feature = "grpc")]
#[cfg_attr(docsrs, doc(cfg(feature = "grpc")))]
pub mod grpc;

/// WebTransport server support over QUIC.
#[cfg(all(feature = "webtransport", not(feature = "compio")))]
#[cfg_attr(docsrs, doc(cfg(feature = "webtransport")))]
pub mod webtransport;

/// Starts the HTTP/3 server with QUIC transport.
///
/// HTTP/3 provides improved performance through QUIC's features like reduced
/// latency, better multiplexing, and built-in encryption.
///
/// # Examples
///
/// ```rust,no_run
/// # #[cfg(feature = "http3")]
/// use tako::{serve_h3, router::Router};
///
/// # #[cfg(feature = "http3")]
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
/// let router = Router::new();
/// serve_h3(router, "[::]:4433", Some("cert.pem"), Some("key.pem")).await;
/// # Ok(())
/// # }
/// ```
#[cfg(all(feature = "http3", not(feature = "compio")))]
#[cfg_attr(docsrs, doc(cfg(feature = "http3")))]
pub use server_h3::serve_h3;
#[cfg(all(feature = "http3", not(feature = "compio")))]
#[cfg_attr(docsrs, doc(cfg(feature = "http3")))]
pub use server_h3::serve_h3_with_shutdown;
/// Starts the HTTPS server with TLS encryption support.
///
/// Similar to `serve` but enables TLS encryption for secure connections. Requires
/// the "tls" feature to be enabled and proper TLS configuration.
///
/// # Examples
///
/// ```rust,no_run
/// # #[cfg(feature = "tls")]
/// use tako::{serve_tls, router::Router};
/// # #[cfg(feature = "tls")]
/// use tokio::net::TcpListener;
///
/// # #[cfg(feature = "tls")]
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
/// let listener = TcpListener::bind("127.0.0.1:8443").await?;
/// let router = Router::new();
/// // serve_tls(listener, router, tls_config).await;
/// # Ok(())
/// # }
/// ```
#[cfg(all(not(feature = "compio"), feature = "tls"))]
#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
pub use server_tls::serve_tls;
#[cfg(all(not(feature = "compio"), feature = "tls"))]
#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
pub use server_tls::serve_tls_with_shutdown;
#[cfg(feature = "compio-tls")]
#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
pub use server_tls_compio::serve_tls;
#[cfg(feature = "compio-tls")]
#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
pub use server_tls_compio::serve_tls_with_shutdown;

/// Global memory allocator using jemalloc for improved performance.
#[cfg(feature = "jemalloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "jemalloc")))]
#[global_allocator]
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;