域名 AXUM.RS 将于 2025 年 10 月到期。我们无意再对其进行续费,如果你有意接续这个域名,请与我们取得联系。
  • AXUM.RS 现仅需人民币 3000 元(大写:叁仟元整。接受适度议价
  • 按照行业规则,AXUM.RS 到期后,大概率会进入长时间的赎回期,该期间内,如果你想拥有该域名,将要付出高额的费用
  • 我们已启用 AXUM.EU.ORG 域名,并将持续运营
  • 仅接受微信或支付宝交易
如果你对 AXUM.RS 有兴趣,请和我们进行联系:

axum错误处理

最近TG 群很多朋友讨论到,在接收 JSON 数据时,如何对用户错误提交的数据回复自定义的信息。在axum 官方示例中,有一个通过自定义 extractor 的示例,同时axum 文档里有一篇专门介绍的错误处理的文档。

本章将简化官方的 extractor 以及结合 nginx 来实现。

自定义 extractor

extractor 的定义

axum 官方已经提供了很多 extractor,其中包括 axum::Json。现在,我们要实现自己的 Json extractor——当然,为了避免混乱,建议取别的名字,比如MyJson等。

// src/extract.rs

// 定义自己的Json extract
pub struct Json<T>(pub T);

// 实现FromRequest

#[async_trait]
impl<B, T> FromRequest<B> for Json<T>
where
    B: axum::body::HttpBody + Send,
    T: DeserializeOwned,
    B::Data: Send,
    B::Error: Into<BoxError>,
{
    type Rejection = (StatusCode, axum::Json<serde_json::Value>);

    async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
        match axum::Json::<T>::from_request(req).await {
            Ok(value) => Ok(Self(value.0)),
            Err(err) => {
                let body: Cow<'_, str> = match err {
                    JsonRejection::InvalidJsonBody(err) => {
                        format!("缺少所需的字段:{}", err).into()
                    }
                    JsonRejection::MissingJsonContentType(err) => {
                        format!("请使用JSON请求:{}", err).into()
                    }
                    err => format!("发生错误:{}", err).into(),
                };
                Err((
                    StatusCode::BAD_REQUEST,
                    axum::Json(json!({ "error": body })),
                ))
            }
        }
    }
}

如果你对中间件还有印象,你会发现这段代码何其的熟悉。

nginx

server {
    listen 443 ssl;
    server_name axum.rs;

    error_page 400 401 403 404 405 500 501 502 503 504 /msg.json;
    location /msg.json {
        internal;
        default_type application/json;
        charset utf-8;
        return 400 '{"error":"请检查你提交的数据"}';
    }
}
要查看完整内容,请先登录