统一错误处理系统 (Error 和 Result<T>)
为了构建一个健壮、可维护且对开发者友好的应用,我们建立了一套统一的错误处理系统。该系统的核心是自定义的 enum Error 和全局的 type Result<T> = std::result::Result<T, Error>。
Error 和 Result<T>)为了构建一个健壮、可维护且对开发者友好的应用,我们建立了一套统一的错误处理系统。该系统的核心是自定义的 enum Error 和全局的 type Result<T> = std::result::Result<T, Error>。
tracing)一个健壮的日志系统是可观测性 (Observability) 的基石,对于应用的调试、性能监控和事后审计至关重要。我们的项目采用 Rust 生态中最先进的 tracing 框架来构建一个高性能、结构化、可配置的日志系统。
本文档将详细解析我们日志系统的设计理念、核心特性以及如何在代码中正确地使用它。
中间件是我们应用中处理 HTTP 请求的核心机制。它允许我们在请求到达最终的业务处理函数 (Handler) 之前或之后,执行一系列通用的、可复用的操作,例如日志记录、身份验证、权限检查等。
我们的中间件系统遵循经典的 “洋葱模型 (Onion Model)”。你可以将每个中间件想象成一层洋葱皮,请求从外层穿透到内层,最终到达核心(Handler),然后响应再从内层穿透回外层。
ApiResponse<T>为了确保我们的 API 接口具有一致性、可预测性,并让前后端开发者都能轻松协作,我们实现了一套标准化的 API 响应结构,即 ApiResponse<T>。
这个模块处理了所有创建 HTTP 响应、设置状态码和格式化 JSON 的模板代码,使得我们的业务逻辑(在 Handler 和 Service 中)能够更加简洁,并专注于核心功能。
WebPath)为了构建一个可扩展、易于维护且具备自动化能力的大型 Web 应用,我们没有直接使用 Axum 的 Router 来零散地注册路由,而是设计了一套更高级的、基于 WebPath 结构体的 声明式路由构建系统。
这套系统的核心思想是:先将应用的全部路由结构描述为一个数据树 (Data Tree),然后再将这个树“编译”成一个真正的 Axum Router。
VForm<T>)在处理表单提交 (form submissions) 时,我们不仅需要从请求中解析数据,更重要的是要 验证 这些数据的合法性,例如检查字段是否为空、邮箱格式是否正确、字符串长度是否在规定范围内等。
传统的做法是在 Handler 函数内部手动调用验证逻辑,这会导致代码冗长、重复且容易出错。
VJson<T>)在现代前后端分离的 Web 应用中,JSON 是最主要的数据交换格式。当后端接收到来自客户端的 JSON 请求体时,我们不仅需要将其反序列化为 Rust 结构体,更重要的是要 验证 这些数据的合法性。
与处理表单类似,传统的做法是在 Handler 函数内部手动调用验证逻辑。为了遵循 DRY (Don't Repeat Yourself) 原则并提升代码质量,我们创建了一个自定义的 Axum 提取器 (Extractor)——VJson<T> (Validated JSON)。
VQuery<T>)在处理 GET 请求时,我们经常需要从 URL 的查询字符串 (Query String) 中提取参数,用于分页、排序、筛选等功能。例如 /users?page_num=1&page_size=20。
与处理请求体一样,对这些查询参数进行 验证 是至关重要的,以防止无效的输入(如负数页码)导致程序错误或安全漏洞。