Documentation / Architecture d'un projet Runique / Stack Middleware
Stack Middleware
Ordre des slots
Runique applique les middlewares dans un ordre optimal via le système de slots :
Requête entrante
↓
1. Extensions (slot 0) → Injection Tera, Config, Engine
2. TrustedProxies (slot 2) → IP cliente réelle
3. Compression (slot 5) → Compression externe
4. CORS (slot 8) → Avant ErrorHandler (preflight OPTIONS)
5. ErrorHandler (slot 10) → Capture et rendu des erreurs
6. HostValidation (slot 15) → Validation Allowed Hosts
7. HttpsRedirect (slot 17) → Redirection HTTPS derrière un proxy (ENFORCE_HTTPS, sans ACME)
8. Custom (slot 20+) → Middlewares personnalisés
9. OpenRedirect (slot 25) → Inspection des réponses 3xx
10. Security Headers (slot 30) → CSP (avec son nonce), HSTS, X-Frame-Options, etc.
11. Cache (slot 40) → No-cache en développement
12. Session (slot 50) → Gestion des sessions
13. SessionUpgrade (slot 55) → Lecture/écriture en session
14. Auth (slot 57) → Relit en base le compte de la session (CurrentUser)
15. CSRF (slot 60) → Protection CSRF
16. AntiBot (slot 65) → Honeypot
↓
Handler (votre code)
↓
Réponse sortante (middlewares en sens inverse)
Important : Avec Axum, le dernier
.layer()appliqué est le premier exécuté. Le Builder Intelligent gère cet ordre automatiquement.
Middlewares personnalisés : ils prennent les slots 20, 21… dans leur ordre d'enregistrement, donc avant Session (50), Auth (57) et CSRF (60). Ils ne voient ni la session ni le compte connecté (
CurrentUser). Au plus 5 : le 6ᵉ tomberait sur le slot 25 d'OpenRedirect, et le démarrage s'arrête sur une panique (collision de slots).
Injection de dépendances
Via les Extensions Axum, injectées automatiquement par le middleware Extensions :
// Enregistré automatiquement par le builder :
// Extension(engine) → Arc<RuniqueEngine>
// Extension(tera) → Arc<Tera>
// Extension(config) → Arc<RuniqueConfig>
// Accessible dans les handlers via Request :
pub async fn handler(request: Request) -> AppResult<Response> {
let db = request.engine.db.clone();
let config = &request.engine.config;
// ...
}