Catcher

如果請求返回的 Response 的狀態碼是錯誤, 而頁麵裏麵的 Body 是空, 這時 salvo 會試圖使用 Catcher 捕獲這個錯誤, 顯示一個友好的錯誤頁麵.

一種簡單的創建自定義 Catcher 的方法是, 通過 Catcher::default() 返回一個係統默認的 Catcher, 然後講它添加到 Service 上.

use salvo::catcher::Catcher;

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

默認的 Catcher 實現 CatcherImpl 捕獲處理錯誤, 發送默認的錯誤頁麵. 默認的錯誤支持以 XML, JSON, HTML, Text 格式發送錯誤頁麵.

可以通過給這個默認的 Catcher 添加 hoop 的方式, 把自定義的錯誤捕獲程序添加到Catcher上. 這個錯誤捕獲的程序依然是 Handler.

use salvo::catcher::Catcher;
use salvo::prelude::*;

#[handler]
async fn hello() -> &'static str {
    "Hello World"
}
#[handler]
async fn error500(res: &mut Response) {
    res.set_status_code(StatusCode::INTERNAL_SERVER_ERROR);
}

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

    let acceptor = TcpListener::new("127.0.0.1:5800").bind().await;
    Server::new(acceptor).serve(create_service()).await;
}

fn create_service() -> Service {
    let router = Router::new()
        .get(hello)
        .push(Router::with_path("500").get(error500));
    Service::new(router).with_catcher(Catcher::default().hoop(handle404))
}

#[handler]
async fn handle404(&self, _req: &Request, _depot: &Depot, res: &mut Response, ctrl: &mut FlowCtrl) {
    if let Some(StatusCode::NOT_FOUND) = res.status_code() {
        res.render("Custom 404 Error Page");
        ctrl.skip_rest();
    }
}
[package]
name = "example-custom-error-page"
version = "0.1.0"
edition = "2021"
publish = false


[dependencies]
salvo.workspace = true
tokio = { version = "1", features = ["macros"] }
tracing = "0.1"
tracing-subscriber = "0.3"