"The power of Rust. Modern DX. LLM-ready."
"API surface is ours, engines can change."
This single principle drives every architectural decision in RustAPI. You write code against a stable, ergonomic API. We handle the complexity of HTTP protocols, async runtimes, and serialization libraries internally.
Building APIs in Rust traditionally requires:
- Understanding
hyper's low-level HTTP primitives - Managing
tokioruntime configurations - Fighting trait bounds like
Pin<Box<dyn Future<...>>> - Writing boilerplate for request parsing, validation, and error handling
- Manually documenting every endpoint
The result? Simple APIs take 100+ lines. Developers spend more time on plumbing than business logic.
RustAPI provides a facade — a clean, stable API that wraps all the complexity:
// This is all you need. No boilerplate.
use rustapi_rs::prelude::*;
#[rustapi_rs::get("/users/{id}")]
async fn get_user(Path(id): Path<u64>) -> Json<User> {
Json(User::find(id).await)
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
RustApi::auto().run("0.0.0.0:8080").await
}5 lines. Auto-generated OpenAPI. Production-ready.
Every feature must be expressible in minimal code.
| Framework | Hello World Lines |
|---|---|
| Raw Hyper | ~50 lines |
| Axum | ~15 lines |
| RustAPI | 5 lines |
We achieve this through:
- Sensible defaults (auto-route registration, built-in Swagger UI)
- Derive macros that eliminate boilerplate
- A prelude that exports everything you need
Your code depends only on rustapi-rs. Internal dependencies are hidden.
# Your Cargo.toml - simple and stable
[dependencies]
rustapi-rs = "0.1.335"You never write:
# ❌ Not this - internal details exposed
hyper = "1.0"
tokio = "1.35"
validator = "0.16"Benefits:
- No dependency conflicts
- Simpler
Cargo.toml - We can upgrade internals without breaking your code
The facade pattern lets us swap implementations freely.
| Component | Current Engine | Could Become |
|---|---|---|
| HTTP Server | hyper 1.x |
hyper 2.x, h3 (HTTP/3) |
| Async Runtime | tokio |
smol, async-std (future) |
| Validation | Native RustAPI v2 (legacy optional) | Further optimized native engine |
| Router | matchit |
Custom radix tree |
| OpenAPI | Native implementation | Further optimized native implementation |
Example scenario: When hyper 2.0 releases with breaking changes:
- We update
rustapi-coreto usehyper 2.0 - We bump
rustapi-rsto0.2.0 - Your code stays exactly the same — just update the version
Everything you need, nothing you don't.
# Just the basics
rustapi-rs = "0.1.335"
# Kitchen sink
rustapi-rs = { version = "0.1.335", features = ["full"] }
# Pick what you need
rustapi-rs = { version = "0.1.335", features = ["extras-jwt", "extras-cors", "protocol-toon"] }| Feature | What You Get |
|---|---|
extras-jwt |
JWT authentication with AuthUser<T> extractor |
extras-cors |
CORS middleware with builder pattern |
extras-rate-limit |
IP-based rate limiting |
protocol-toon |
LLM-optimized TOON format |
core-openapi |
Auto-generated /docs endpoint |
full |
All features enabled |
Built for the AI era.
Traditional JSON:
{"users":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}],"total":2}→ ~20 tokens
TOON format:
users[(id:1,name:Alice)(id:2,name:Bob)]total:2
→ ~9 tokens (55% savings)
RustAPI provides:
Toon<T>— Direct TOON responsesLlmResponse<T>— Content negotiation with token counting headersAcceptHeader— Automatic format detection
#[rustapi_rs::get("/ai/data")]
async fn ai_endpoint(accept: AcceptHeader) -> LlmResponse<Data> {
LlmResponse::new(data, accept.preferred)
}
// Response headers: X-Token-Count-JSON, X-Token-Count-TOON, X-Token-Savings// ❌ We don't expose hyper types
fn handler(req: hyper::Request<...>) -> hyper::Response<...>
// ✅ We provide our own abstractions
fn handler(req: Request) -> impl IntoResponse// ❌ Not this
let server = Server::builder()
.http1_header_max_size(8192)
.http1_only(true)
.tcp_keepalive(Some(Duration::from_secs(60)))
.build(...);
// ✅ This
RustApi::new().run("0.0.0.0:8080").await// ❌ Not this
where
T: Service<Request<Body>, Response = Response<ResBody>> + Clone + Send + 'static,
T::Error: Into<BoxError>,
T::Future: Send,
ResBody: Body<Data = Bytes> + Send + 'static,
ResBody::Error: Into<BoxError>,
// ✅ Just this
async fn handler(Json(body): Json<T>) -> Json<R>| Goal | Target | Achieved |
|---|---|---|
| Hello World | ≤ 5 lines | ✅ 5 lines |
| CRUD tutorial | ≤ 15 min | ✅ ~10 min |
| First Swagger UI | Zero config | ✅ Auto at /docs |
| Compile errors | Understandable | ✅ Clear hints |
| LLM token savings | ≥ 50% | ✅ 50-58% |
- Polish existing features
- Performance optimizations (
core-simd-json, better allocations) - More middleware (compression, static files)
- Custom validation engine (remove
validatordependency) - Async validation support
- Stable API guarantee
- WebSocket support
- GraphQL (optional crate)
- gRPC (optional crate)
- HTTP/3 via
h3(transparent upgrade)
RustAPI is not just another web framework. It's a philosophy:
- Simplicity first — 5 lines to production
- Stability always — Your code never breaks
- Future-ready — Built for AI, ready for anything
use rustapi_rs::prelude::*;
// This will work in 2024, 2025, and beyond.
// Engines change. Your code doesn't."API surface is ours, engines can change."