错误处理与 ProblemDetails
Error 类型
框架统一错误类型 `webx::Error`:
pub enum Error {
NotFound(String),
Validation(String),
Serialization(serde_json::Error),
Http(String),
Di(String),
Internal(String),
Message(String),
Routing(String),
}
HTTP 状态码映射
| Error 变体 | HTTP 状态码 | 典型场景 | |-----------|-----------|---------| | `NotFound` | 404 | 资源不存在 | | `Validation` | 400 | 业务校验失败 | | `Serialization` | 400 | JSON 解析错误 | | `Http` | 400/401/403 | 认证失败、权限不足 | | `Di` | 500 | DI 解析失败 | | `Internal` | 500 | 未预期内部错误 | | `Message` | 500 | 通用错误 | | `Routing` | 404 | 路由错误 |
默认错误响应格式
{
"error": "User abc not found",
"status": 404
}
由内置异常中间件自动生成,无需在 Handler 中手动设置状态码。
Handler 中的错误处理
async fn handle(&self, req: GetUserRequest) -> Result<UserDto> {
// 资源不存在
let user = self.repo.find(&req.id)
.ok_or_else(|| Error::NotFound(format!("User {} not found", req.id)))?;
// 业务校验
if user.is_banned {
return Err(Error::Http("Account is banned".into()));
}
Ok(user)
}
? 运算符
let data = self.external_api.fetch().await
.map_err(|e| Error::Internal(e.to_string()))?;
ProblemDetails(RFC 7807)
框架支持标准化问题详情:
use webx::{ProblemDetails, FieldError};
let problem = ProblemDetails::validation_error()
.with_title("Validation failed")
.with_detail("One or more fields are invalid")
.with_field_errors(vec![
FieldError { field: "email".into(), message: "Invalid format".into() },
]);
适用于需要结构化错误信息的公共 API。
错误处理最佳实践
| 实践 | 说明 | |------|------| | 可预期错误用 Error 变体 | 不用 panic | | 404 用 NotFound | 不要用 Internal 代替 | | 校验失败用 Validation | 与序列化错误区分 | | 认证/授权用 Http | 或依赖中间件统一处理 | | 不要泄露内部细节 | Internal 消息不暴露堆栈给客户端 |
小结
返回 `Result<T>` 即可,框架负责 Error → HTTP 的映射。需要结构化错误时使用 `ProblemDetails`。
下一章:[DI 与生命周期](../06-di-lifecycle/INDEX.md)