01. Actix-web CRUD Implementation
This section provides a complete, production-ready example of a CRUD (Create, Read, Update, Delete) application using Actix-web and an in-memory store.
1. Project Dependencies
Add these to your Cargo.toml:
[dependencies]
actix-web = "4.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
uuid = { version = "1.0", features = ["v4", "serde"] }2. The Data Model
We’ll use serde for JSON serialization and uuid for unique identifiers.
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Serialize, Deserialize, Clone)]
pub struct Task {
pub id: Option<Uuid>,
pub title: String,
pub description: String,
pub completed: bool,
}3. Shared Application State
In-memory state is shared across handlers using Arc and Mutex.
use std::sync::{Arc, Mutex};
pub struct AppState {
pub tasks: Mutex<Vec<Task>>,
}4. CRUD Handlers
Create Task
use actix_web::{post, web, HttpResponse, Responder};
#[post("/tasks")]
async fn create_task(data: web::Data<AppState>, mut task: web::Json<Task>) -> impl Responder {
let mut tasks = data.tasks.lock().unwrap();
task.id = Some(Uuid::new_v4());
tasks.push(task.into_inner());
HttpResponse::Ok().json(tasks.last().unwrap())
}Read All Tasks
use actix_web::{get};
#[get("/tasks")]
async fn get_tasks(data: web::Data<AppState>) -> impl Responder {
let tasks = data.tasks.lock().unwrap();
HttpResponse::Ok().json(&*tasks)
}Update Task
use actix_web::{put};
#[put("/tasks/{id}")]
async fn update_task(
data: web::Data<AppState>,
path: web::Path<Uuid>,
task_update: web::Json<Task>,
) -> impl Responder {
let mut tasks = data.tasks.lock().unwrap();
let id = path.into_inner();
if let Some(task) = tasks.iter_mut().find(|t| t.id == Some(id)) {
task.title = task_update.title.clone();
task.description = task_update.description.clone();
task.completed = task_update.completed;
return HttpResponse::Ok().json(task);
}
HttpResponse::NotFound().body("Task not found")
}Delete Task
use actix_web::{delete};
#[delete("/tasks/{id}")]
async fn delete_task(data: web::Data<AppState>, path: web::Path<Uuid>) -> impl Responder {
let mut tasks = data.tasks.lock().unwrap();
let id = path.into_inner();
if let Some(pos) = tasks.iter().position(|t| t.id == Some(id)) {
tasks.remove(pos);
return HttpResponse::NoContent().finish();
}
HttpResponse::NotFound().body("Task not found")
}5. Main Server Setup
use actix_web::{App, HttpServer};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let app_state = web::Data::new(AppState {
tasks: Mutex::new(vec![]),
});
HttpServer::new(move || {
App::new()
.app_data(app_state.clone())
.service(create_task)
.service(get_tasks)
.service(update_task)
.service(delete_task)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}This concludes the Rust University Curriculum. You have now learned the foundations, advanced concepts, and how to build a real-world web application.