Capturer les Panics dans les Requêtes
Le middleware Catch Panic permet d'intercepter les plantages qui surviennent lors du traitement des requêtes par l'application. Pour les détails de l'API, veuillez consulter la documentation.
Note: Pour utiliser CatchPanic
, vous devez activer la fonctionnalité catch-panic
dans Cargo.toml
:
salvo= { version = "xxx", features = ["catch-panic"] }
Présentation du Middleware
CatchPanic
est un middleware qui capture les panics dans les handlers. Lorsqu'un panic survient pendant le traitement d'une requête, il l'intercepte et renvoie une réponse 500 Internal Server Error au lieu de faire crasher tout le serveur.
Important: Ce middleware doit être utilisé en premier pour garantir qu'il capture bien les panics provenant des autres middlewares ou handlers.
Utilisation Basique
use salvo_core::prelude::*;
use salvo_extra::catch_panic::CatchPanic;
#[handler]
async fn hello() {
panic!("panic error!");
}
#[tokio::main]
async fn main() {
let router = Router::new().hoop(CatchPanic::new()).get(hello);
let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
Server::new(acceptor).serve(router).await;
}
Comparaison avec d'autres Frameworks pour une Compréhension Rapide
Axum
Équivalent du middleware catch_panic
de Tower
dans Axum:
use axum::{
Router,
routing::get,
http::StatusCode,
};
use tower::ServiceBuilder;
use tower_http::catch_panic::CatchPanicLayer;
async fn panic_handler() -> &'static str {
panic!("panic error!");
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/", get(panic_handler))
.layer(
ServiceBuilder::new()
.layer(CatchPanicLayer::new())
);
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
Gin (Go)
Dans le framework Gin en Go, l'équivalent est le middleware Recovery:
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default() // Inclut par défaut le middleware Recovery
r.GET("/", func(c *gin.Context) {
panic("panic error!")
})
r.Run(":8080")
}
Exemple de Code
catch-panic/src/main.rs
use salvo::prelude::*;
// Handler that deliberately panics to demonstrate panic catching
#[handler]
async fn hello() {
panic!("panic error!");
}
#[tokio::main]
async fn main() {
// Initialize logging system
tracing_subscriber::fmt().init();
// Set up router with CatchPanic middleware to handle panics gracefully
// This prevents the server from crashing when a panic occurs in a handler
let router = Router::new().hoop(CatchPanic::new()).get(hello);
// Bind server to port 5800 and start serving
let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
Server::new(acceptor).serve(router).await;
}