Capture des Paniques dans les Requêtes

Capture de Panique est utilisé pour intercepter les plantages survenant pendant le traitement des requêtes dans le programme. Pour les API spécifiques, veuillez consulter la documentation.

Note : Pour utiliser CatchPanic, vous devez activer la fonctionnalité catch-panic dans Cargo.toml :

salvo = { version = "xxx", features = ["catch-panic"] }

Introduction au Middleware

CatchPanic est un middleware conçu pour intercepter les paniques dans les gestionnaires. Lorsqu'une panique survient pendant le traitement d'une requête, il la capture et écrit une erreur 500 Internal Server Error dans la réponse, empêchant ainsi le serveur entier de planter.

Note importante : Ce middleware doit être utilisé comme premier middleware pour garantir qu'il puisse intercepter les paniques provenant d'autres middlewares ou gestionnaires.

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:8698").bind().await;
    Server::new(acceptor).serve(router).await;
}

Comparaison avec d'autres Frameworks pour une Compréhension Rapide du Concept

Axum

Similaire au middleware catch_panic dans Tower d'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 du langage Go, similaire au middleware Recovery :

package main

import (
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default() // Inclut le middleware Recovery par défaut
    
    r.GET("/", func(c *gin.Context) {
        panic("panic error!")
    })
    
    r.Run(":8080")
}

Exemple de Code

main.rs
Cargo.toml
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 8698 and start serving
    let acceptor = TcpListener::new("0.0.0.0:8698").bind().await;
    Server::new(acceptor).serve(router).await;
}