域名 AXUM.RS 将于2025年10月到期。我们无意再对其进行续费,我们希望你能够接续这个域名,让更多 AXUM 开发者继续受益。
  • 方案1️⃣AXUM.RS 域名 = 3000
  • 方案2️⃣方案1️⃣ + 本站所有专题原始 Markdown 文档 = 5000
  • 方案3️⃣方案2️⃣ + 本站原始数据库 = 5500
如果你有意接续这份 AXUM 情怀,请与我们取得联系。
说明:
  1. 如果有人购买 AXUM.RS 域名(方案1️⃣),或者该域名到期,本站将启用新的免费域名继续提供服务。
  2. 如果有人购买了 AXUM.RS 域名,且同时购买了内容和/或数据库(方案2️⃣/方案3️⃣),本站将关闭。届时我们或许会以另一种方式与你再相遇。

自定义响应

我们的 Todo 服务是对外提供 API 的服务,它的响应格式总是JSON类型。为此,我们可以定义响应类型,以简化 handler 的编写。

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

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

自定义响应

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

  • code:响应状态码,如果没有错误,该值为0

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

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

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,这个路径有两个问题:

  • 略显冗长

  • 模块名和结构体同名

略显冗长

为了便于其它模块引用这个结构体,我们在src/main.rs中对其进行重导出:

pub use response::Response;

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

crate::Response;

在 handler 中使用自定义响应

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

pub async fn usage<'a>() -> Result<Json<Response<Vec<&'a str>>>> {
    let data = r#"
        GET /todo -- 获取所有待办列表
        POST /todo -- 添加待办列表
        GET /todo/:list_id -- 获取待办列表详情
        DELETE /todo/:list_id -- 删除指定的待办列表,包括其所有待办事项
        PUT /todo/:list_id -- 修改待办列表
        GET /todo/:list_id/items -- 获取待办列表的所有待办事项
        GET /todo/:list_id/items/:item_id -- 获取待办事项的详情
        PUT /todo/:list_id/items/:item_id -- 修改待办事项(将其的状态修改为“已完成”)
        DELETE /todo/:list_id/items/:item_id -- 删除待办事项
    "#;
    let data: Vec<&str> = data
        .split('\n')
        .into_iter()
        .map(|line| line.trim())
        .filter(|line| !line.is_empty())
        .collect();
    let data = Response::ok(data);
    Ok(Json(data))
}

注意:

  • 这里使用的是 crate::Result

  • 这里使用的是 crate::Response

这里使用的是 crate::Result

这里使用的是 crate::Response

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

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

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

要查看完整内容,请先登录