REST API
Why Rust for Web & Application Development?
Rust is used for backend APIs because it offers:
- High performance (comparable to C/C++)
- Memory safety without garbage collection
- Strong type system → fewer runtime bugs
- Excellent concurrency model (async/await)
Popular Rust web frameworks include Actix, Axum, and Rocket.
Actix Web
- Built on the actor model and async Rust.
- Very fast and production-ready.
- Slightly steeper learning curve.
Features
- Asynchronous handlers
- Middleware support
- JSON serialization/deserialization
- Strong ecosystem
Step 1: Add dependencies (Cargo.toml)
[dependencies]
actix-web = "4"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Step 2: Code (main.rs)
use actix_web::{web, App, HttpServer, Responder, HttpResponse};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct User {
id: u32,
name: String,
}
// GET /user/{id}
async fn get_user(path: web::Path<u32>) -> impl Responder {
let user = User {
id: path.into_inner(),
name: "Alice".to_string(),
};
HttpResponse::Ok().json(user)
}
// POST /user
async fn create_user(user: web::Json<User>) -> impl Responder {
HttpResponse::Created().json(user.into_inner())
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/user/{id}", web::get().to(get_user))
.route("/user", web::post().to(create_user))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
#[derive(Serialize, Deserialize)]: Enables JSON conversion.web::Path<u32>: Extractsidfrom the URL.web::Json<User>: Parses JSON body into aUser.HttpResponse::Ok().json(user): Sends JSON response.
Axum
- Built by the Tokio + Tower team.
- Very modular and modern.
- Emphasizes type-safe request handling.
- Excellent for async-heavy services.
Step 1: Dependencies
[dependencies]
axum = "0.7"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Step 2: Code (main.rs)
use axum::{
routing::{get, post},
Json, Router,
};
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;
#[derive(Serialize, Deserialize)]
struct User {
id: u32,
name: String,
}
// GET /user/:id
async fn get_user(axum::extract::Path(id): axum::extract::Path<u32>) -> Json<User> {
Json(User {
id,
name: "Alice".to_string(),
})
}
// POST /user
async fn create_user(Json(user): Json<User>) -> Json<User> {
Json(user)
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/user/:id", get(get_user))
.route("/user", post(create_user));
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
println!("Server running on {}", addr);
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
Router::new().route(...): Defines API routes.Path(id): Extracts route parameter.Json(user): Extracts JSON body.- Handlers return
Json<T>directly.
Axum focuses heavily on type safety and composability.
Rocket
- Known for its simplicity and developer experience.
- Uses procedural macros for routing.
- Very expressive and beginner-friendly.
- Slightly less flexible than Axum but easier to use.
Step 1: Dependencies
[dependencies]
rocket = { version = "0.5.0-rc.3", features = ["json"] }
serde = { version = "1", features = ["derive"] }
Step 2: Code (main.rs)
#[macro_use] extern crate rocket;
use rocket::serde::{Serialize, Deserialize, json::Json};
#[derive(Serialize, Deserialize)]
struct User {
id: u32,
name: String,
}
#[get("/user/<id>")]
fn get_user(id: u32) -> Json<User> {
Json(User {
id,
name: "Alice".to_string(),
})
}
#[post("/user", format = "json", data = "<user>")]
fn create_user(user: Json<User>) -> Json<User> {
user
}
#[launch]
fn rocket() -> _ {
rocket::build()
.mount("/", routes![get_user, create_user])
}
#[get("/user/<id>")]: Defines a GET route with a parameter.#[post(...)]: Defines a POST route expecting JSON.Json<T>: Automatically serializes/deserializes JSON.#[launch]: Entry point for Rocket.
Rocket’s macros reduce boilerplate and make routing very readable.
Comparison Table
| Feature | Actix Web | Axum | Rocket |
|---|---|---|---|
| Performance | ⭐⭐⭐⭐⭐ (Very fast) | ⭐⭐⭐⭐⭐ (Very fast) | ⭐⭐⭐⭐ |
| Ease of Use | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Type Safety | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| Async Support | Yes | Yes (Tokio-native) | Yes |
| Macros | Minimal | Minimal | Heavy use |
| Best For | High-performance production APIs | Modern, scalable async services | Learning, rapid development |
Which One Should You Choose?
- Choose Rocket if:
- You’re new to Rust web development.
- You want readable, concise code.
- Choose Axum if:
- You want modern async architecture.
- You care about composability and type safety.
- Choose Actix if:
- You want maximum performance.
- You’re building a high-load production system.