Introduction aux Frameworks web (axum / actix)
Rust est reconnu pour :
- ses performantes,
- la sécurité mémoire et
- sa faible empreinte de ressources.
Deux frameworks dominent aujourd’hui le paysage pour le développement d’API et de services web backend :
- Actix Web : historique, ultra-rapide, basé sur les acteurs et
- Axum : moderne, développé par l’équipe Tokio, basé sur la composition.
Axum : Le framework moderne de l’écosystème Tokio
Axum intègre l’écosystème tokio et les middlewares tower.
- Routage déclaratif : Les routes sont chaînées de manière fluide.
- Extracteurs (Extractors) : Les arguments des fonctions de gestion (handlers) déterminent automatiquement ce qui doit être extrait de la requête (JSON, paramètres, headers) grâce au système de types de Rust.
use axum::{routing::{get, post}, Json, Router};
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct NouvelUtilisateur {
nom: String,
}
#[derive(Serialize)]
struct Utilisateur {
id: u64,
nom: String,
}
#[tokio::main]
async fn main() {
// Construction des routes
let app = Router::new()
.route("/", get(racine))
.route("/utilisateurs", post(creer_utilisateur));
// Lancement du serveur avec Tokio
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
async fn racine() -> &'static str {
"Bienvenue sur l'API Axum !"
}
// L'argument Json<NouvelUtilisateur> est un extracteur
async fn creer_utilisateur(Json(payload): Json<NouvelUtilisateur>) -> Json<Utilisateur> {
let utilisateur = Utilisateur {
id: 1,
nom: payload.nom,
};
Json(utilisateur) // Sérialisé automatiquement en JSON
}
Actix Web
Actix Web a longtemps été le framework de référence pour sa vitesse pure (souvent en tête des benchmarks TechEmpower).
Il utilise son propre runtime optimisé au-dessus de Tokio et repose sur un modèle d’exécution par thread très strict.
- Macros d’attributs : Utilise des attributs comme
#[get("/")]pour lier les fonctions aux routes. - État partagé : L’état de l’application est injecté via
web::Data.
use actix_web::{get, post, web, App, HttpServer, Responder, HttpResponse};
use serde::Deserialize;
#[derive(Deserialize)]
struct Info {
projet: String,
}
#[get("/")]
async fn index() -> impl Responder {
HttpResponse::Ok().body("Bienvenue sur l'API Actix Web !")
}
#[post("/configuration")]
async fn configurer(form: web::Json<Info>) -> impl Responder {
format!("Configuration reçue pour le projet : {}", form.projet)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// Le serveur instancie une fabrique d'application par thread système
HttpServer::new(|| {
App::new()
.service(index)
.service(configurer)
})
.bind(("127.0.0.1:8080"))?
.run()
.await
}
Comparatif
| Critère | Axum | Actix Web |
|---|---|---|
| Écosystème | Intégration parfaite avec tokio, tower (middlewares) et hyper. | Propre écosystème (actix-rt, actix-net). |
| Style d’écriture | Basé sur les fonctions, les extracteurs et la composition. | Basé sur les macros d’attributs et une configuration orientée objet. |
| Courbe d’apprentissage | Plus naturelle si l’on maîtrise déjà Tokio et les types génériques complexes. | Plus proche des frameworks traditionnels (comme Express ou Actix dans d’autres langages). |
| Gestion des erreurs | Repose sur le système de conversion de types (IntoResponse). | Utilise un trait spécifique ResponseError. |
| Performance | Excellente, largement suffisante pour l’immense majorité des cas. | Légèrement supérieure en performance brute pure sur des micro-benchmarks. |