tgin 0.1.0

Universal traffic glue: a Rust construction kit for gateways — HTTP, Telegram bots, RabbitMQ, Kafka, WebSocket tunnels
Documentation
 __                          
/\ \__         __            
\ \ ,_\    __ /\_\    ___    
 \ \ \/  /'_ `\/\ \ /' _ `\  
  \ \ \_/\ \L\ \ \ \/\ \/\ \ 
   \ \__\ \____ \ \_\ \_\ \_\
    \/__/\/___L\ \/_/\/_/\/_/
           /\____/           
           \_/__/

any traffic in - any traffic out. A Rust construction kit for building gateways of your own shape: one core, endless batteries

ci

HISTORY | DEMOS | EXAMPLES

[!IMPORTANT] active development is continuing: there is no stable version yet

Why Tgin?

  • Composability: every gateway is ingress → egress; balancers, routers and retries are decorators that wrap egresses — new behavior without touching the core

  • Type safety: an incompatible ingress/egress pair is a failure to compile

  • Batteries included: HTTP server & client, Telegram Bot API (longpoll and webhook), RabbitMQ, Kafka, WebSocket tunnels, round-robin / fan-out balancers, predicate router, retry with backoff

  • Honest delivery: the reply of every message doubles as its ack — RabbitMQ ack/nack/requeue and Telegram offset advancement are driven by the real downstream outcome

  • Backpressure end to end: full channels turn into HTTP 429 and broker qos instead of unbounded memory

  • Per-key ordering: messages with the same key (one Telegram chat, one entity) stay ordered, different keys run in parallel

  • Graceful shutdown: SIGINT drains in-flight messages, then stops

  • Embeddable: tgin is a library, not a daemon — your gateway is a ~20 line Rust binary you fully control

Architecture Overview

   ingress                     egress
HTTP | Telegram | RabbitMQ | Kafka | Tunnel
     ↓
   Envelope<I, O>  (data + meta + reply)
     ↓
 [ Route | RoundRobin | All | Retry ]
     ↓
HTTP | Telegram | RabbitMQ | Kafka | Tunnel

Quick start

# Clone the repository
git clone https://github.com/chesnokpeter/tgin.git
cd tgin

# Run a case
cargo run --example reverse_proxy
BOT_TOKEN=... cargo run --example telegram_balancer
TUNNEL_TOKEN=... cargo run --example tunnel_server

# Or bring up a full live stack (broker + backends + tgin)
cd demos/kafka-bridge && docker compose up --build

Use as a library

tgin is a library crate — your gateway is your own ~20 line binary:

[dependencies]
tgin = { git = "https://github.com/chesnokpeter/tgin", branch = "main" }

Configuration

Your gateway is a Rust builder — every piece is a value you construct and compose:

let server = HttpServer::new("0.0.0.0:8080");
let http = HttpClient::new();

Tgin::new()
    .pipeline(
        HttpIngress::catch_all(&server),
        Route::new()
            .when(
                |request: &RequestData| request.uri.path().starts_with("/api"),
                RoundRobin::new()
                    .to(HttpEgress::new(&http, "http://127.0.0.1:3001"))
                    .to(HttpEgress::new(&http, "http://127.0.0.1:3002")),
            )
            .otherwise(HttpEgress::new(&http, "http://127.0.0.1:3000")),
    )
    .run()
    .await;

Cases

one core, different hands:

nginx case — reverse proxy with routing, balancing and failover → examples/reverse_proxy.rs

ngrok case — expose localhost to the internet through a WebSocket tunnel (in NAT) → examples/tunnel_server.rs + examples/tunnel_client.rs

telegram case — the original tgin: balance updates across bot instances, webhook or longpoll on both sides, per-chat ordering for free. Bots can even poll tgin itself — it recreates Telegram getUpdates semantics inside your cluster, offsets included → examples/telegram_balancer.rs, examples/telegram_webhook_balancer.rs, examples/telegram_longpoll_balancer.rs

bridge case — HTTP in, broker out; queue in, Telegram message out. One binary can run several pipelines at once → examples/http_to_rabbit.rs, examples/rabbit_to_telegram.rs, examples/ingestion_pipeline.rs, examples/kafka_bridge.rs

gateway case — hide your bot token behind your own API → examples/telegram_api_gateway.rs

Demos

live compose stacks under demos/ — real brokers, real backends, failure drills to run yourself:

  • demos/reverse-proxy — routing + balancing, kill a backend and watch failover
  • demos/tunnel — reach a container that publishes no ports, kill the agent and watch it reconnect
  • demos/ingestion — HTTP → RabbitMQ at-least-once, kill the worker and nothing is lost
  • demos/kafka-bridge — HTTP → Kafka → worker with honest offset commits

each is one docker compose up --build plus a README walkthrough

Batteries

kind battery what it does
ingress HttpIngress serve a path, a method or catch-all on a shared HttpServer
ingress KafkaIngress consume a topic in a consumer group; offsets commit only after downstream confirms, failures seek back and redeliver
ingress TelegramBotPollingIngress getUpdates longpoll from Telegram, offset advances only after delivery, per-chat key
ingress TelegramBotWebhookIngress webhook endpoint with x-telegram-bot-api-secret-token validation
ingress RabbitmqIngress consume a durable queue, qos prefetch, ack/nack/requeue by outcome
ingress TunnelIngress agent side of the tunnel: outbound connect + reconnect
egress HttpEgress forward to an upstream with proper proxy headers
egress KafkaEgress produce with acks=all; meta.key becomes the partition key, so per-chat / per-entity order survives the hop
egress TelegramBotWebhookEgress push updates to a bot instance the way Telegram does, secret header included
egress TelegramBotPollingEgress host a getUpdates endpoint — unmodified longpoll bots poll tgin as if it were Telegram, ack by offset
egress TelegramBotApiEgress call the Bot API: fixed method or pass-through, 429/5xx/4xx mapped honestly
egress RabbitmqEgress publish persistent messages with publisher confirms
egress TunnelEgress server side of the tunnel: multiplex requests over one WebSocket
decorator Route pick an egress by predicate, otherwise fallback
decorator RoundRobin rotate across egresses, failover on retryable errors
decorator All fan out every message to every egress
decorator Retry retry retryable errors with exponential backoff
shared HttpServer / HttpClient / Rabbit resources you construct once and share across batteries

Future features

  • Config file on top of compiled batteries — declare pipelines in a config instead of Rust, validated at startup, invalid pairs rejected before serving (Envoy/Vector style)
  • Hot config reload — swap pipeline wiring on the fly, without restarting the process
  • Transform / processing decorators — map, filter and enrich messages between ingress and egress
  • Metrics, tracing, logging
  • TLS termination
  • Streaming bodies & WebSocket passthrough
  • More batteries: NATS, Redis, gRPC
  • Performance harness

Main Goal

Provide a universal, embeddable toolkit where any traffic can be taken in, routed, distributed and transformed on the way out — one frozen core, endless batteries