Catcher

Cuando un Response devuelve un código de estado de error y el Body dentro de la página está vacío, Salvo intentará capturar este error usando un Catcher y mostrará una página de error amigable para el usuario.

Puedes obtener un Catcher predeterminado del sistema llamando a Catcher::default(), y luego agregarlo al Service.

use salvo::catcher::Catcher;

Service::new(router).catcher(Catcher::default());

El Catcher predeterminado admite el envío de páginas de error en formatos XML, JSON, HTML y Text.

Puedes agregar manejadores de captura de errores personalizados al Catcher adjuntando hoops a este Catcher predeterminado. Estos manejadores de captura de errores siguen siendo del tipo Handler.

Puedes agregar múltiples manejadores de captura de errores personalizados al Catcher a través de hoops. Los manejadores de errores personalizados pueden llamar al método FlowCtrl::skip_next después de procesar un error para omitir los manejadores de errores posteriores y retornar anticipadamente.

main.rs
Cargo.toml
use salvo::catcher::Catcher;
use salvo::prelude::*;

// Handler that returns a simple "Hello World" response
#[handler]
async fn hello() -> &'static str {
    "Hello World"
}

// Handler that deliberately returns a 500 Internal Server Error
#[handler]
async fn error500(res: &mut Response) {
    res.status_code(StatusCode::INTERNAL_SERVER_ERROR);
}

#[tokio::main]
async fn main() {
    // Initialize logging system
    tracing_subscriber::fmt().init();

    // Create and start server with custom error handling
    let acceptor = TcpListener::new("0.0.0.0:8698").bind().await;
    Server::new(acceptor).serve(create_service()).await;
}

// Create service with custom error handling
fn create_service() -> Service {
    // Set up router with two endpoints:
    // - / : Returns "Hello World"
    // - /500 : Triggers a 500 error
    let router = Router::new()
        .get(hello)
        .push(Router::with_path("500").get(error500));

    // Add custom error catcher for 404 Not Found errors
    Service::new(router).catcher(Catcher::default().hoop(handle404))
}

// Custom handler for 404 Not Found errors
#[handler]
async fn handle404(&self, _req: &Request, _depot: &Depot, res: &mut Response, ctrl: &mut FlowCtrl) {
    // Check if the error is a 404 Not Found
    if StatusCode::NOT_FOUND == res.status_code.unwrap_or(StatusCode::NOT_FOUND) {
        // Return custom error page
        res.render("Custom 404 Error Page");
        // Skip remaining error handlers
        ctrl.skip_rest();
    }
}