A blazing fast, lightweight web framework for Rust
Ignite your development journey with performance and elegance
Getting Started β’ Documentation β’ Examples β’ Benchmarks
π Major Performance Improvements
- 94% Latency Reduction: Middleware chain optimization (30ms β 1.9ms)
- 40% Memory Reduction: Optimized body handling with direct
Bytesusage - 51,574 req/sec: Production-ready throughput competing with Axum
π― Breaking Changes
- Radix-only routing (removed Base router mode)
- Unified
Json<T>type for both extraction and response - Optimized body types (
Arc<Bytes>βBytes)
π¨ Enhanced Developer Experience
- New
IntoResponsetrait for ergonomic responses - Support for returning primitives (bool, numbers, Option, Result)
- Comprehensive documentation with examples
See CHANGELOG.md for complete details and migration guide.
- Features
- Quick Start
- Core Concepts
- Performance
- Documentation
- Examples
- Middleware
- State Management
- Error Handling
- Feature Flags
- Migration from v0.2.3
- Roadmap
- Contributing
- License
- π Blazing Fast: High-performance Radix tree routing with O(log n) lookup
- π₯ Zero-Cost Abstractions: Compile-time optimizations with minimal runtime overhead
- π¨ Ergonomic API: Intuitive builder pattern inspired by Axum and Actix
- π‘οΈ Type-Safe: Leverage Rust's type system for compile-time guarantees
- π Middleware: Composable middleware system with
from_fnhelper - π¦ State Management: Built-in support for shared application state
- π Secure by Default: HTTPS/TLS, CORS, security headers, and rate limiting
- π WebSocket Support: Full-featured WebSocket implementation
- π Rich Extractors: Path, Query, Json, Form, Headers, Cookies, State
- β¨ IntoResponse Trait: Return any type that implements
IntoResponse - π― Unified Json: Single
Json<T>type for both input and output - π Performance: 94% latency reduction through middleware optimization
- π Documentation: Comprehensive rustdoc coverage with examples
- π§ Simplified API: Radix-only routing, infallible response builders
Add Ignitia to your Cargo.toml:
[dependencies]
ignitia = "0.2.4"
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }use ignitia::{Router, Server};
use std::net::SocketAddr;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a simple router
let router = Router::new()
.get("/", || async { "Hello, World! π₯" });
// Start the server
let addr = SocketAddr::from((, 3000));
println!("π₯ Server running on http://{}", addr);
Server::new(router, addr).ignitia().await?;
Ok(())
}use ignitia::{Router, Json, Path, Query, Result};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
struct User {
id: u32,
name: String,
email: String,
}
#[derive(Deserialize)]
struct CreateUser {
name: String,
email: String,
}
#[derive(Deserialize)]
struct SearchParams {
q: String,
page: Option<u32>,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let router = Router::new()
// List users with pagination
.get("/users", |Query(params): Query<SearchParams>| async move {
let page = params.page.unwrap_or(1);
Json(vec![
User { id: 1, name: "Alice".into(), email: "alice@example.com".into() },
User { id: 2, name: "Bob".into(), email: "bob@example.com".into() },
])
})
// Get user by ID
.get("/users/{id}", |Path(id): Path<u32>| async move {
Json(User {
id,
name: "Alice".into(),
email: "alice@example.com".into(),
})
})
// Create new user
.post("/users", |Json(user): Json<CreateUser>| async move {
Json(User {
id: 1,
name: user.name,
email: user.email,
})
})
// Update user
.put("/users/{id}", |Path(id): Path<u32>, Json(user): Json<CreateUser>| async move {
Json(User {
id,
name: user.name,
email: user.email,
})
})
// Delete user
.delete("/users/{id}", |Path(id): Path<u32>| async move {
format!("Deleted user {}", id)
});
let addr = SocketAddr::from((, 3000));
println!("π₯ API running on http://{}", addr);
Server::new(router, addr).ignitia().await?;
Ok(())
}Return any type that implements IntoResponse:
use ignitia::{Router, Json, StatusCode};
use http::StatusCode;
let router = Router::new()
// Simple string
.get("/", || async { "Hello!" })
// With status code
.post("/users", || async {
(StatusCode::CREATED, "User created")
})
// JSON response
.get("/api/data", || async {
Json(serde_json::json!({ "status": "ok" }))
})
// Boolean (returns JSON true/false)
.get("/health", || async { true })
// Numbers (returns as text/plain)
.get("/count", || async { 42 })
// Option (auto 404 if None)
.get("/find/{id}", |Path(id): Path<u32>| async move {
database.find(id).await.map(Json)
})
// Result with automatic error handling
.get("/users", || async {
let users = fetch_users().await?;
Ok::<_, Error>(Json(users))
});v0.2.4: Exclusively uses high-performance Radix tree routing
use ignitia::Router;
let router = Router::new()
// Static routes
.get("/", home)
.get("/about", about)
// Path parameters
.get("/users/{id}", get_user)
.get("/posts/{slug}", get_post)
// Multiple parameters
.get("/users/{user_id}/posts/{post_id}", get_user_post)
// Wildcard routes
.get("/files/{*path}", serve_file);Performance: O(log n) lookup, zero allocations, 51,574 req/sec
Type-safe request data extraction:
use ignitia::{Path, Query, Json, State, Headers};
use serde::Deserialize;
#[derive(Deserialize)]
struct UserParams {
id: u32,
}
#[derive(Deserialize)]
struct SearchQuery {
q: String,
page: u32,
}
#[derive(Deserialize)]
struct CreateData {
name: String,
}
// Multiple extractors (up to 16)
async fn handler(
Path(params): Path<UserParams>,
Query(search): Query<SearchQuery>,
Json(data): Json<CreateData>,
State(db): State<Database>,
headers: Headers,
) -> Json<Response> {
// Use extracted data
Json(response)
}Organize routes by feature:
// API v1 routes
let api_v1 = Router::new()
.get("/users", list_users_v1)
.post("/users", create_user_v1);
// API v2 routes
let api_v2 = Router::new()
.get("/users", list_users_v2)
.post("/users", create_user_v2);
// Main router
let app = Router::new()
.get("/", home)
.nest("/api/v1", api_v1)
.nest("/api/v2", api_v2);Test Setup: wrk -c100 -d30s http://localhost:3000/
Throughput: 51,574 req/sec
Latency: 1.90ms avg, 10.60ms max
Transfer: 7.97 MB/sec
Consistency: 70.54% within 1 std dev
| Metric | v0.2.3 | v0.2.4 | Improvement |
|---|---|---|---|
| Avg Latency | 30ms | 1.9ms | 94% β |
| Allocations | baseline | -40% | 40% β |
| Throughput | ~45K RPS | 51.5K RPS | 14.5% β |
- Middleware Chain: Pre-compiled at startup, lock-free runtime access
- Body Handling: Direct
Bytesusage, zero-copy for static content - Route Matching: Radix tree with O(log n) lookup, no regex compilation
- Response Building: Infallible builders, inline optimizations
| Framework | Throughput | Latency (avg) |
|---|---|---|
| Ignitia v0.2.4 | 51,574 RPS | 1.90ms |
| Axum | ~50-70K RPS | ~2-3ms |
| Actix Web | ~60-80K RPS | ~1-2ms |
| Rocket | ~40-50K RPS | ~3-4ms |
Competitive with industry-leading frameworks while maintaining ease of use.
- API Reference - Complete API documentation
- Routing Guide - Advanced routing patterns
- Response Guide - Response types and IntoResponse
- Middleware Guide - Custom middleware creation
- State Management - Sharing state across handlers
- Error Handling - Error types and handling
- WebSocket Guide - Real-time communication
- TLS/HTTPS Guide - Secure connections
- docs.rs - Comprehensive API documentation
- Examples - Working code examples
- CHANGELOG.md - Version history and migration guides
use ignitia::{Router, middleware::{LoggerMiddleware, CorsMiddleware}};
let router = Router::new()
.middleware(LoggerMiddleware::new())
.middleware(CorsMiddleware::new())
.get("/api/users", list_users);use ignitia::middleware::from_fn;
let auth = from_fn(|req, next| async move {
if let Some(token) = req.headers.get("Authorization") {
if verify_token(token).await {
return next.run(req).await;
}
}
Response::new(StatusCode::UNAUTHORIZED)
});
let router = Router::new()
.middleware(auth)
.get("/protected", secret_handler);use std::sync::Arc;
use ignitia::{Router, State};
#[derive(Clone)]
struct AppState {
db: Arc<Database>,
}
async fn get_user(
Path(id): Path<u32>,
State(state): State<AppState>
) -> Json<User> {
let user = state.db.find_user(id).await;
Json(user)
}
let state = AppState {
db: Arc::new(Database::connect().await),
};
let router = Router::new()
.state(state)
.get("/users/{id}", get_user);#[cfg(feature = "websocket")]
use ignitia::websocket::{WebSocketConnection, Message};
#[cfg(feature = "websocket")]
let router = Router::new()
.websocket("/ws", |mut ws: WebSocketConnection| async move {
while let Some(msg) = ws.recv().await {
match msg {
Message::Text(text) => {
ws.send_text(format!("Echo: {}", text)).await?;
}
Message::Close(_) => break,
_ => {}
}
}
Ok(())
});#[cfg(feature = "tls")]
use ignitia::Server;
let router = Router::new()
.get("/", || async { "Secure!" });
Server::new(router, addr)
.enable_https("cert.pem", "key.pem")?
.ignitia()
.await?;use ignitia::{
Router,
middleware::{
LoggerMiddleware,
CorsMiddleware,
RateLimitingMiddleware,
SecurityMiddleware,
RequestIdMiddleware,
CompressionMiddleware,
BodySizeLimitMiddleware,
}
};
let router = Router::new()
.middleware(LoggerMiddleware::new())
.middleware(CorsMiddleware::new())
.middleware(RateLimitingMiddleware::per_minute(100))
.middleware(SecurityMiddleware::high_security())
.middleware(RequestIdMiddleware::new())
.middleware(CompressionMiddleware::new())
.middleware(BodySizeLimitMiddleware::new(10 * 1024 * 1024)); // 10MBuse ignitia::{middleware::from_fn, Request, Response, Next};
let custom = from_fn(|req: Request, next: Next| async move {
println!("Before handler");
let response = next.run(req).await;
println!("After handler");
response
});Share state across handlers:
use std::sync::Arc;
use tokio::sync::RwLock;
use ignitia::{Router, State};
#[derive(Clone)]
struct AppState {
db: Arc<Database>,
cache: Arc<RwLock<HashMap<String, String>>>,
}
let state = AppState {
db: Arc::new(Database::new()),
cache: Arc::new(RwLock::new(HashMap::new())),
};
let router = Router::new()
.state(state)
.get("/users", |State(state): State<AppState>| async move {
// Use state.db or state.cache
Json(users)
});use ignitia::{Error, Result};
async fn handler() -> Result<Json<User>> {
let user = database.find_user(1).await?; // ? works!
Ok(Json(user))
}use ignitia::IntoResponse;
#[derive(Debug)]
struct MyError(String);
impl IntoResponse for MyError {
fn into_response(self) -> Response {
Response::new(StatusCode::BAD_REQUEST)
.with_body(self.0)
}
}Enable optional features in your Cargo.toml:
[dependencies]
ignitia = {
version = "0.2.4",
features = ["tls", "websocket", "self-signed"]
}tls- HTTPS/TLS support with rustlswebsocket- WebSocket protocol supportself-signed- Generate self-signed certificates for development
// β v0.2.3
let router = Router::new()
.with_mode(RouterMode::Radix);
// β
v0.2.4
let router = Router::new(); // Always uses Radix// β v0.2.3
response.body = Arc::new(Bytes::from(data));
// β
v0.2.4
response.body = Bytes::from(data);// β v0.2.3
async fn handler() -> Result<Response> {
Response::json(data)? // Double Result
}
// β
v0.2.4
async fn handler() -> impl IntoResponse {
Json(data) // Clean and simple
}// β v0.2.3
use ignitia::handler::extractor::Json as JsonExtractor;
use ignitia::response::Json as JsonResponse;
// β
v0.2.4
use ignitia::Json; // One type for both!
async fn handler(Json(data): Json<Input>) -> Json<Output> {
Json(output)
}See CHANGELOG.md for complete migration guide.
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
# Clone the repository
git clone https://github.com/AarambhDevHub/ignitia.git
cd ignitia
# Run tests
cargo test
# Run benchmarks
cargo bench
# Check formatting
cargo fmt -- --check
# Run clippy
cargo clippy -- -D warnings
This project is licensed under the MIT License - see the LICENSE file for details.
If you find Ignitia helpful, consider supporting the project:
Design patterns and inspiration from:
- Axum - Middleware patterns, extractors, IntoResponse
- Actix Web - Performance optimizations
- Rocket - Response type ergonomics
Built with β€οΈ using:
- Tokio - Async runtime
- Hyper - HTTP implementation
- Serde - Serialization
- Tower - Service abstractions
π₯ Ignite your development journey with Ignitia! π₯
β Star us on GitHub β’ π Read the Docs β’ π¬ Join Discussion β’ π¬ Discord β’ β Support