自定义响应

本章代码在03/自定义响应分支。

自定义响应

声明response模块,并定义相关的数据结构:

// src/response.rs

#[derive(Serialize)]
pub struct Response<T: Serialize> {
    pub code: i32,
    pub msg: String,
    pub data: Option<T>,
}
  • code:响应状态码,如果没有错误,该值为0

  • msg:提示信息,如果没有错误,该值为OK

  • data:响应的数据。如果发生错误,该值为null(Rust 里的None

为了以 JSON 作为响应,这个结构体以及包括data在内的所有字段必须是可序列化的,即实现了Serialize trait。

impl<T> Response<T>
where
    T: Serialize,
{
    pub fn new(code: i32, msg: String, data: Option<T>) -> Self {
        Self { code, msg, data }
    }
    pub fn ok(data: T) -> Self {
        Self::new(0, "OK".to_string(), Some(data))
    }
    pub fn err(code: i32, msg: String) -> Self {
        Self::new(code, msg, None)
    }
}
  • new():创建一个新的响应

  • ok():创建一个没有错误发生响应

  • err():创建一个发生错误的响应

重导出 Response

目前,Response结构体的引用路径是crate::response::Response,这个路径有两个问题:

  • 略显冗长

  • 模块名和结构体同名

pub use response::Response;

现在它的引用路径变成了:

crate::Response;

在 handler 中使用自定义响应

现在我们把自定义响应和上一章所述的错误处理中实现的自己的Result(注意,别忘了被它隐藏的AppError)在 handler 中使用:

  • 这里使用的是 crate::Result

  • 这里使用的是 crate::Response

为了加强印象,请再看一遍crate::Result的定义:

type Result<T> = std::result::Result<T, error::AppError>;

在自定义错误中使用自定义响应

之前我们的自定义错误的 IntoResponse 直接使用的是 Stringinto_response(),现在我们将它改成使用我们自定义响应的 JSON 响应:

impl IntoResponse for AppError {
    type Body = Full<Bytes>;
    type BodyError = Infallible;

    fn into_response(self) -> axum::http::Response<Self::Body> {
        let code = (&self).code();
        let msg = match self.message {
            Some(msg) => msg,
            None => "有错误发生".to_string(),
        };
        let res: Response<()> = Response::err(code, msg);
        Json(res).into_response()
    }
}
要查看完整内容,请先登录