Introduction : pourquoi Rust pour une API REST ?
\nRust est un langage de programmation système moderne qui combine les performances du C++ et la sécurité mémoire. Ces dernières années, il est devenu un choix populaire pour la création de services web à forte charge. Si vous connaissez déjà Python et souhaitez essayer quelque chose de nouveau, Rust sera un excellent pas en avant.
\nDans cet article, nous allons créer une API REST complète pour gérer une liste de tâches (Todo List) en Rust en utilisant le framework Actix-web. L'ensemble du processus ne prendra pas plus de 30 minutes si vous suivez les instructions.
\n\n1. Préparation de l'environnement
\nInstallation de Rust
\nSi vous n'avez pas encore installé Rust, exécutez la commande dans un terminal (Linux/macOS) :
\ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\nPour Windows, téléchargez l'installateur depuis le site officiel.
\nAprès l'installation, vérifiez la version :
\nrustc --version\n\nCréation du projet
\nCréons un nouveau projet avec Cargo, le gestionnaire de paquets de Rust :
\ncargo new rust_todo_api\ncd rust_todo_api\n\nAjout des dépendances
\nOuvrez le fichier Cargo.toml et ajoutez les dépendances suivantes :
[dependencies]\nactix-web = "4"\nactix-rt = "2"\nserde = { version = "1", features = ["derive"] }\nserde_json = "1"\ntokio = { version = "1", features = ["full"] }\nEnregistrez le fichier. Cargo téléchargera automatiquement toutes les bibliothèques lors de la première compilation.
\n\n2. Création du modèle de données et du stockage
\nAvant d'écrire les endpoints, définissons la structure des données. Nous utiliserons un simple vecteur en mémoire (pour la démonstration).
\n\nModèle de tâche
\nCréez le fichier src/models.rs :
use serde::{Deserialize, Serialize};\n\n#[derive(Debug, Serialize, Deserialize, Clone)]\npub struct Task {\n pub id: u32,\n pub title: String,\n pub completed: bool,\n}\n\nStockage global
\nDans src/main.rs, ajoutons un état global. Pour la sécurité des threads, utilisons Mutex :
use std::sync::Mutex;\nuse actix_web::{web, App, HttpServer, HttpResponse, HttpRequest, Responder};\nuse models::Task;\n\nmod models;\n\nstruct AppState {\n tasks: Mutex<Vec<Task>>,\n next_id: Mutex<u32>,\n}\n\n3. Implémentation des endpoints CRUD
\nÉcrivons maintenant les gestionnaires principaux. Tous recevront l'état de l'application via web::Data.
GET /tasks — récupération de toutes les tâches
\nasync fn get_tasks(data: web::Data<AppState>) -> impl Responder {\n let tasks = data.tasks.lock().unwrap();\n HttpResponse::Ok().json(tasks.clone())\n}\n\nPOST /tasks — création d'une nouvelle tâche
\nasync fn create_task(data: web::Data<AppState>, body: web::Json<Task>) -> impl Responder {\n let mut tasks = data.tasks.lock().unwrap();\n let mut next_id = data.next_id.lock().unwrap();\n let new_task = Task {\n id: *next_id,\n title: body.title.clone(),\n completed: false,\n };\n tasks.push(new_task.clone());\n *next_id += 1;\n HttpResponse::Created().json(new_task)\n}\n\nGET /tasks/{id} — récupération d'une tâche par ID
\nasync fn get_task(data: web::Data<AppState>, path: web::Path<u32>) -> impl Responder {\n let id = path.into_inner();\n let tasks = data.tasks.lock().unwrap();\n match tasks.iter().find(|t| t.id == id) {\n Some(task) => HttpResponse::Ok().json(task),\n None => HttpResponse::NotFound().json("Tâche non trouvée"),\n }\n}\n\nDELETE /tasks/{id} — suppression d'une tâche
\nasync fn delete_task(data: web::Data<AppState>, path: web::Path<u32>) -> impl Responder {\n let id = path.into_inner();\n l