rust-camel
Build integration routes in Rust or YAML using Tower-native pipelines.
rust-camel connects timers, HTTP APIs, files, Kafka, Redis, SQL, and other
systems through composable message routes. Use it when you need Apache
Camel-style routing and Enterprise Integration
Patterns (EIP) without a JVM — every processor and producer is a
Service<Exchange>, so EIP patterns compose as Tower middleware.
Status: Pre-release. APIs may change. Requires Rust 1.89 or newer (stable).
Table of Contents
- What is rust-camel?
- Quick Start
- Core Concepts
- Components & EIP Patterns
- REST DSL & OpenAPI
- Configuration
- Error Handling
- Observability
- Security
- Docker
- Examples
- Architecture
- Building & Testing
- Status & Roadmap
- Contributing
- License
What is rust-camel?
A Rust-native integration framework that routes messages between components using a fluent builder API or a declarative YAML DSL. The data plane (processing, EIP patterns, middleware) is Tower-native; the control plane (components, endpoints, consumers, route lifecycle, supervision) uses its own trait hierarchy.
Who is it for?
- Integration, platform, and DevOps engineers — design and run routes with
camel-cliand YAML, with configuration profiles, health endpoints, Prometheus/OpenTelemetry, and container images — often without writing Rust. - Backend, data, and API teams — connect APIs, brokers, databases, files, and event streams (HTTP, WebSocket, Kafka, MQTT, JMS, gRPC, SOAP, SQL, XML, LLMs) using reusable routing and transformation patterns, and expose them through the REST DSL with schema validation and OpenAPI generation.
- Rust and Tower developers — embed routes with
RouteBuilder, add custom processors or components, and compose pipelines as TowerService<Exchange>services. - Apache Camel users and JVM migration teams — evaluate Camel-inspired
routing in native Rust, with single-binary deployment and scratch
amd64/arm64images, without assuming drop-in compatibility.
From glue scripts to AI pipelines, edge deployments to legacy-system bridges — if it involves routing messages between systems, rust-camel is built for the shape of the problem.
Why rust-camel?
- Composable by construction — EIP patterns are Tower layers; chain them
the same way you chain
tower::Service. - Single binary, scratch containers — ship routes as one Rust binary or a minimal Docker image.
- Declarative or code — define routes in YAML with JSON-Schema validation and editor autocomplete, or in pure Rust.
When not to use it
- You need a stable, production-hardened integration runtime — rust-camel is pre-release; APIs will change.
- You already live on the JVM and depend on Apache Camel's ecosystem.
- Your workload is pure request/response without routing, EIP patterns, or multi-system orchestration (a plain web framework is simpler).
Quick Start
Run an example
A route receives an Exchange from timer:tick and sends it to log:info.
Your first route (Rust)
use ;
use ;
use LogComponent;
use TimerComponent;
use CamelContext;
async
Your first route (YAML)
# routes/hello.yaml
routes:
- id: "hello-timer"
from: "timer:tick?period=1000"
steps:
- to: "log:info"
Save it as routes/hello.yaml and run with camel run.
Use the CLI
See crates/camel-cli/README.md for all commands.
Core Concepts
- Route — a pipeline from a source (
from:) through a sequence of steps (to:, processors, EIP patterns) to one or more sinks. - Exchange — the message envelope flowing through a route: headers, body, and a unique correlation id for tracing.
- Component — a connector (
timer,http,kafka, ...) that creates Endpoints from URIs liketimer:tick?period=1000. - EIP pattern — a routing/transformation step (filter, split, choice, aggregate, ...) applied as Tower middleware on the data plane.
Components & EIP Patterns
Components: timer, cron, log, direct, seda, file, http,
ws/wss, kafka, mqtt, redis, sql, surrealdb, opensearch, jms,
grpc, cxf (SOAP), xslt, xj (XML↔JSON), validator, container
(Docker), controlbus, master, exec, keycloak, wasm, llm. See
crates/components/ for the full set of
implementations.
Enterprise Integration Patterns (all chainable as Tower layers):
| Pattern | Builder method |
|---|---|
| Content-Based Router | .choice() / .when() |
| Filter | .filter(predicate) |
| Splitter (incl. streaming) | .split(config) |
| Aggregator | .aggregate(config) |
| Multicast | .multicast() |
| Recipient List | .recipient_list(config) |
| Routing Slip | .routing_slip(expr) |
| Dynamic Router | .dynamic_router(expr) |
| Wire Tap | .wire_tap(uri) |
| Load Balancer | .load_balance() |
| Throttler | .throttle(n, duration) |
| Delayer | .delay() |
| Loop | .loop_count(n) |
| Content Enricher | .enrich(uri) / .poll_enrich(uri, timeout) |
| Marshal / Unmarshal | .marshal(fmt) / .unmarshal(fmt) |
| Stream Cache | .stream_cache(n) |
| try / catch / finally | .do_try() / .do_catch() / .do_finally() |
Marshal formats: JSON, XML, CSV, ZIP.
REST DSL & OpenAPI
Define REST APIs declaratively in YAML with automatic JSON binding, path templates, schema validation, and OpenAPI generation.
rest:
- host: 0.0.0.0
port: 8080
path: /api/users
operations:
- method: GET
operation_id: listUsers
to: direct:listUsers
produces: application/json
- method: POST
operation_id: createUser
consumes: application/json
produces: application/json
success_status: 201
to: direct:createUser
request_schema:
type: object
properties:
name:
email:
required:
The rest: block lowers to http: consumer routes with JSON unmarshalling,
schema validation (→ 400 on failure), and default status codes.
Generate an OpenAPI 3.0.3 document:
See examples/rest-crud/ for a complete runnable CRUD
example with in-memory storage and static file co-hosting.
Configuration
External configuration via Camel.toml (loaded by the camel-config crate):
[]
= ["routes/**/*.yaml"]
= "INFO"
# Component defaults — apply to all endpoints; URI params always override these
[]
= 5000
= false
[]
= "localhost:9092"
= "camel"
[]
= "localhost"
= 6379
[]
= true
= 9090
[]
= "ERROR"
[]
= "prod-kafka:9092"
Profiles, discovery, and overrides
- Profiles — multiple environments (
[default],[production], ...) in one file, selected withCAMEL_PROFILE=production. - Route discovery —
routes = ["routes/**/*.yaml"]loads routes via glob. - Environment overrides — any value via
CAMEL_*env vars (CAMEL_LOG_LEVEL=DEBUG,CAMEL_ROUTES_0="custom/*.yaml"). - Deep merge — nested configs merge; URI parameters always win.
Optional components (http, ws, kafka, redis, sql, jms, file, container)
implement ComponentBundle, owning their config key and schemes. See
examples/custom-component-bundle/ to
build your own.
Error Handling
Retry with exponential backoff and jitter, plus a dead-letter channel:
use ErrorHandlerConfig;
use Duration;
let error_handler = dead_letter_channel
.on_exception
.retry
.with_backoff
.with_jitter // ±20% (recommended 0.1–0.3)
.build;
The same route in YAML:
# routes/retry.yaml
routes:
- id: "retry-example"
from: "direct:input"
error_handler:
dead_letter_channel: "log:errors"
on_exceptions:
- kind: "Io"
retry:
max_attempts: 3
initial_delay_ms: 100
multiplier: 2.0
max_delay_ms: 10000
jitter_factor: 0.2
steps:
- to: "log:info"
During retries these headers are set automatically: CamelRedelivered,
CamelRedeliveryCounter, CamelRedeliveryMaxCounter.
Exception disposition
Each handler controls what happens after it runs:
| Disposition | Behavior |
|---|---|
Propagate |
Re-throw upstream after the handler runs (default) |
Handled |
Absorb as Ok(Exchange); pipeline stops |
Continued |
Clear the error; pipeline continues to the next step |
Configure the same in YAML via error_handler: with retry:, jitter_factor:,
on_exceptions:, and continued: true / handled: true (mutually exclusive).
See examples/error-handling/ for complete
examples.
Observability
- Correlation IDs — every exchange carries a unique
correlation_id. - Prometheus — export via
PrometheusService(implements theLifecycletrait); metrics includecamel_exchanges_total,camel_errors_total,camel_exchange_duration_seconds,camel_queue_depth,camel_circuit_breaker_state. - OpenTelemetry — tracing and metrics export via
camel-otel. - Health endpoints —
/healthz(liveness),/readyz(readiness),/health(detailed report), ready for Kubernetes probes.
use SocketAddr;
use PrometheusService;
use CamelContext;
let prometheus = new;
let mut ctx = builder
.build
.await?
.with_lifecycle
.with_tracing
.await;
ctx.start.await?;
// Prometheus server + /healthz, /readyz start automatically
Security
rust-camel ships built-in security safeguards:
- SSRF protection (HTTP) — block private IPs by default
(
allowInternal=false) and custom blocklists (blockedHosts=...). - Path traversal protection (File) — resolved paths are validated against
the configured base directory;
../and out-of-base absolute paths are rejected. - Timeouts — configurable on file and HTTP I/O (file
readTimeout/writeTimeout, HTTPconnectTimeout/responseTimeout; defaults 30s). - Memory limits — the aggregator caps
max_bucketsandbucket_ttl.
See SECURITY.md to report vulnerabilities.
Docker
Pre-built images on GHCR
and Docker Hub. Both
variants support linux/amd64 and linux/arm64.
| Tag suffix | Base | Use case |
|---|---|---|
| (none) | scratch | Minimal runtime image, small attack surface |
-alpine |
alpine:3.21 | Debugging — includes a busybox shell |
# Production
# Debugging shell
Examples
The examples/ directory contains 90+ runnable examples. A few
good starting points:
| Example | Shows |
|---|---|
hello-world |
Minimal timer → log route |
rest-crud |
REST DSL + OpenAPI + static co-hosting |
http-server |
HTTP consumer with streaming |
kafka-example |
Kafka producer/consumer |
error-handling |
Retries, dead-letter, dispositions |
custom-component-bundle |
Build your own component |
bean-demo |
Bean registry / dependency injection |
Run any of them with cargo run -p <name>.
Architecture
rust-camel separates two planes:
- Data plane — Tower-native. Every processor and producer is a
Service<Exchange>; EIP patterns compose as Tower middleware. - Control plane — a trait hierarchy (
Component,Endpoint,Consumer) for route lifecycle, supervision, and hot-reload.
┌──────────────────────────────────────────────────────┐
│ Your Application │
│ RouteBuilder / YAML DSL / Camel.toml │
└──────────────────────┬───────────────────────────────┘
│
┌──────────────────────▼───────────────────────────────┐
│ camel-core │
│ CamelContext — composition root │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Data plane (Tower) │ │
│ │ Exchange → Service<Exchange> pipeline │ │
│ │ EIP processors as Tower middleware │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Control plane │ │
│ │ Route lifecycle, supervision, hot-reload │ │
│ └──────────────────────────────────────────────┘ │
└──────────┬──────────────────────────┬────────────────┘
│ │
┌──────────▼─────────┐ ┌───────────▼────────────────┐
│ camel-processor │ │ Components │
│ EIP patterns │ │ timer, log, http, file, │
│ (Tower layers) │ │ kafka, redis, sql, ..., │
└────────────────────┘ └────────────────────────────┘
Internals (domain model, event journaling, runtime state) are an
implementation detail — see crates/camel-core/README.md
and docs/ARCHITECT.md.
JSON Schema for the DSL
The full YAML/JSON route DSL has a published JSON Schema for editor autocomplete and SDK validation:
- URL:
https://raw.githubusercontent.com/kennycallado/rust-camel/main/schemas/dsl/route-schema.json - Local:
schemas/dsl/route-schema.json(regenerate withcargo xtask schema)
Building & Testing
Local lint and schema tools: cargo fmt --check, cargo clippy -- -D warnings,
and the cargo xtask subcommands (lint-unwrap, lint-secrets,
lint-log-levels, schema --check). See AGENTS.md for the exact
CI gate set.
Status & Roadmap
Pre-release — APIs will change. Active development covers component coverage, the DSL surface, and observability.
Contributing
Contributions are welcome. Read CONTRIBUTING.md for build
setup, coding standards, the commit convention, and the CI quality gates your
PR must pass. Open issues and pull requests at
kennycallado/rust-camel.
License
Apache-2.0.