Rust library
Embed tunneling directly in your Rust app with no external process.
Quick start
Cargo.toml
[dependencies] macha = "0.2" tokio = { version = "1", features = ["full"] }
src/main.rs — one-liner
use macha; #[tokio::main] async fn main() -> macha::Result<()> { // blocks until disconnected; auto-reconnects by default macha::start("myapp", 3000).await }
Run in the background alongside your server
use macha::Tunnel; #[tokio::main] async fn main() -> macha::Result<()> { let tunnel = Tunnel::builder("myapp", 3000) .build()?; tokio::spawn(async move { let _ = tunnel.run().await; }); // start your own server here… std::future::pending::<()>().await; Ok(()) }
Builder API
All options are chainable on Tunnel::builder(subdomain, port).
| Method | Type | Description |
|---|---|---|
| .server(host) | &str | Tunnel server hostname (default: "macha.live") |
| .control_port(n) | u16 | Control plane port (default: 9000) |
| .data_port(n) | u16 | Data plane port (default: 9001) |
| .token(t) | &str | Auth token to send on REGISTER |
| .reconnect(bool) | bool | Auto-reconnect on session end (default: true) |
| .ttl(secs) | u64 | Registration TTL in seconds (default: 3600 = 1 hour). Server drops the subdomain when it elapses; with reconnect (default) the agent re-registers automatically. |
| .tls() | — | Enable TLS with Mozilla root certs |
| .tls_custom_ca(path) | PathBuf | Enable TLS with a custom CA cert file |
| .tls_insecure() | — | Enable TLS, skip cert verification (dev only) |
| .log_channel(tx) | broadcast::Sender<RequestLog> | Receive a RequestLog after each completed request |
| .build() | Result<Tunnel> | Validates subdomain, returns Tunnel |
full example
use macha::Tunnel; let tunnel = Tunnel::builder("myapp", 3000) .server("tunnel.yourcompany.com") .token("my-secret-token") .tls() .reconnect(true) .build()?; tunnel.run().await?;
Log channel
Wire a tokio::sync::broadcast channel into the tunnel to receive a RequestLog after every completed request.
use macha::{Tunnel, RequestLog}; use tokio::sync::broadcast; let (tx, mutrx) = broadcast::channel::<RequestLog>(256); // spawn log consumer tokio::spawn(async move { while let Ok(log) = rx.recv().await { println!("{} {} — {}ms", log.method, log.path, log.duration_ms); } }); Tunnel::builder("myapp", 3000) .log_channel(tx) .build()? .run().await?;
RequestLog fields
| Field | Type | Description |
|---|---|---|
| subdomain | String | The registered subdomain |
| method | String | HTTP method (GET, POST, …) |
| path | String | Request path (/api/users, …) |
| bytes_in | u64 | Bytes received from visitor (request) |
| bytes_out | u64 | Bytes sent to visitor (response) |
| duration_ms | u64 | Total time from first byte to connection close |
| timestamp_ms | u128 | Unix epoch milliseconds when request completed |