如何记录Rust Warp框架请求体反序列化失败的错误日志
实现方案
方案1:细粒度仅针对当前接口打日志
直接修改你的with_order_body函数,在反序列化出错时先打印日志再抛出原有错误即可,代码改动最小:
fn with_order_body() -> impl Filter<Extract = (model::Order,), Error = Rejection> + Clone { warp::body::content_length_limit(1024 * 16) .and(warp::body::json()) // 新增错误捕获逻辑 .map_err(|rej: Rejection| { if let Some(deser_err) = rej.find::<warp::body::BodyDeserializeError>() { // 直接打印到标准错误,也可以替换为你项目中使用的日志库(如tracing::error!等) eprintln!("[订单接口反序列化错误] {}", deser_err); } rej }) }
这种方式只会对这个接口的反序列化错误输出日志,不会影响其他路由。
方案2:全局统一处理所有Warp错误日志
如果需要给所有路由的各类错误都加上日志,可以通过Warp的recover机制统一挂载全局错误处理函数:
- 先定义全局错误处理函数
use std::convert::Infallible; use warp::{http::StatusCode, reject::Rejection, reply::Reply}; async fn handle_rejection(rej: Rejection) -> Result<impl Reply, Infallible> { let (status, resp_msg) = if let Some(deser_err) = rej.find::<warp::body::BodyDeserializeError>() { // 反序列化错误处理 eprintln!("[全局反序列化错误] {}", deser_err); (StatusCode::BAD_REQUEST, format!("Request body deserialize error: {}", deser_err)) } else if let Some(_) = rej.find::<warp::reject::MethodNotAllowed>() { // 方法不允许错误处理 (StatusCode::METHOD_NOT_ALLOWED, "Method not allowed".to_string()) } else if let Some(_) = rej.find::<warp::reject::PayloadTooLarge>() { // 长度超限错误处理 (StatusCode::PAYLOAD_TOO_LARGE, "Request body too large".to_string()) } else { // 其他未匹配错误 eprintln!("[未处理请求错误] {:?}", rej); (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error".to_string()) }; Ok(warp::reply::with_status(resp_msg, status)) }
- 在服务启动时挂载全局错误处理
把你原来绑定服务的路由外层加上recover调用即可:
// 假设你的路由整合后叫routes let routes = put_order(repo) // 可追加其他路由配置 .recover(handle_rejection); warp::serve(routes).run(([127, 0, 0, 1], 8080)).await;
这种方式可以一次性处理所有路由的各类错误日志,不需要逐个修改路由逻辑。
内容的提问来源于stack exchange,提问作者kingledion
相关产品推荐
相关产品推荐

