- 内容简介本专题将带你从零开始实现一个简单的、RESTFUL 风格的 Todo 服务。包括:JSON 响应及请求、PostgreSQL 的使用、自定义错误的处理、RESTFul 的定义、配置文件、日志的记录等。
- 配置文件本章我们将实现配置文件的加载。我们将对 axum 的监听地址和 PostgreSQL 相关的信息进行配置,并保存到`.env`文件中。
- 错误处理本章我们将自定义错误、自定义一个`Result`以及让它们作为 handler 的返回值,进行 HTTP 响应。
- 自定义响应我们的 Todo 服务是对外提供 API 的服务,它的响应格式总是`JSON`类型。为此,我们可以定义响应类型,以简化 handler 的编写。
- 数据库、模型、状态共享及TodoList现在是时候开始进行数据库操作,以便实现功能了。本章将实现`TodoList`的功能。
- 日志及重构本章我们将对之前的代码进行重构并且使用日志记录可能发生的错误。
- 实现TodoItem经过一番重构,目前我们的 Todo 服务已经基本完善了,现在只差最后一个部分:TodoItem。本章我们就来实现它。
- 总结经过一番不懈努力,我们终于完成了一个提供 RESTFul API 的 Todo 服务。虽然功能简单,但它涉及到了 Axum 开发的多个方面。
错误处理
本章我们将自定义错误、自定义一个Result以及让它们作为 handler 的返回值,进行 HTTP 响应。
自定义错误
我们将定义自己的错误类型,在项目内都将使用该自定义错误。同时,我们还会将对该自定义错误实现IntoResponse,以便在 handler 中作为返回值使用。
首先,在src/main.rs声明error模块:
/// 错误的类型
pub enum AppErrorType {
    /// 数据库错误
    DbType,
    /// 未找到
    NotFound,
}
/// 应用错误
pub struct AppError {
    /// 错误信息
    pub message: Option<String>,
    /// 错误原因(上一级的错误)
    pub cause: Option<String>,
    /// 错误类型
    pub error_type: AppErrorType,
}
最后,为这个自定义错误实现IntoResponse:
/// 实现 IntoResponse
impl IntoResponse for AppError {
    type Body = Full<Bytes>;
    type BodyError = Infallible;
    fn into_response(self) -> axum::http::Response<Self::Body> {
        let msg = match self.message {
            Some(msg) => msg,
            None => "".to_string(),
        };
        msg.into_response()
    }
}
Rust 允许每个项目定义自己的Result,需要注意的是,每个项目只能定义一次。在src/main.rs定义我们自己的Result:
/// 定义自己的 Result
type Result<T> = std::result::Result<T, error::AppError>;

