axum is a web application framework for Rust that focuses on ergonomics, type safety, and modularity. It is built on top of `tokio`, `hyper`, and `tower`, leveraging their robust and asynchronous foundations to provide a high-performance and scalable platform for building web services and APIs.
Key features and concepts of axum:
1. Type-Safe Routing: axum's routing system allows you to define routes that map incoming requests to specific handler functions. These routes are type-safe, meaning that the compiler helps catch potential errors at compile time, reducing runtime bugs.
2. Extractor System: axum utilizes an innovative extractor system to parse incoming requests. Instead of manually digging through request bodies or headers, you can declare parameters in your handler functions (e.g., `Json<T>`, `Path<T>`, `Query<T>`, `Extension<T>`), and axum will automatically extract and deserialize the relevant data, performing validation where appropriate.
3. Tower Integration: As axum is built on Tower, it fully embraces Tower services and middleware. This allows for powerful request/response processing pipelines, including capabilities like authentication, logging, rate limiting, and error handling, which can be easily composed and reused.
4. State Management/Dependency Injection: You can share application-specific state across your handlers using the `Extension` extractor. This is a clean way to inject dependencies like database connections, configuration, or clients into your handlers without relying on global state.
5. Ergonomics and Simplicity: axum aims to be easy to use and understand, with a clean API that minimizes boilerplate code. Its focus on Rust's async ecosystem makes it a natural fit for building modern, concurrent web applications.
6. Performance: By leveraging `tokio` for async runtime and `hyper` for the HTTP layer, axum inherits their high performance characteristics, making it suitable for demanding applications.
In summary, axum provides a modern, type-safe, and highly performant framework for building web services in Rust, integrating seamlessly with the broader async Rust ecosystem through its foundation on tokio, hyper, and Tower.
Example Code
```rust
use axum::{
routing::{get, post},
extract::{Path, Json},
response::IntoResponse,
http::StatusCode,
Router,
};
use serde::{Deserialize, Serialize};
// Define a simple data structure for our API
#[derive(Debug, Deserialize, Serialize, Clone)]
struct User {
id: u32,
name: String,
}
// In-memory 'database' for demonstration purposes
static mut USERS: Vec<User> = Vec::new();
// Handler for the root path
async fn hello_world() -> String {
"Hello, axum!".to_string()
}
// Handler to get a user by ID
async fn get_user(Path(id): Path<u32>) -> Result<Json<User>, StatusCode> {
// SAFETY: This is unsafe because USERS is mutable static,
// but used for simplicity in a single-threaded example.
// In a real app, use a Mutex or similar synchronization primitive.
let users_guard = unsafe { &USERS };
if let Some(user) = users_guard.iter().find(|u| u.id == id) {
Ok(Json(user.clone()))
} else {
Err(StatusCode::NOT_FOUND)
}
}
// Handler to create a new user
async fn create_user(Json(mut new_user): Json<User>) -> impl IntoResponse {
// SAFETY: See comment in get_user
let users_guard = unsafe { &mut USERS };
if users_guard.iter().any(|u| u.id == new_user.id) {
(StatusCode::CONFLICT, "User with this ID already exists".to_string())
} else {
users_guard.push(new_user.clone());
(StatusCode::CREATED, Json(new_user).into_response())
}
}
#[tokio::main]
async fn main() {
// Initialize some dummy users
// SAFETY: See comment in get_user
unsafe {
USERS.push(User { id: 1, name: "Alice".to_string() });
USERS.push(User { id: 2, name: "Bob".to_string() });
}
// Build our application with a single route
let app = Router::new()
.route("/", get(hello_world))
.route("/users/:id", get(get_user))
.route("/users", post(create_user));
// Run our app with hyper, binding to '127.0.0.1:3000'
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
println!("Listening on {}", listener.local_addr().unwrap());
axum::serve(listener, app).await.unwrap();
}
```








axum