# 错误处理优化说明 ## 📋 优化目标 1. **提升安全性**:不暴露内部技术实现细节 2. **改善用户体验**:提供清晰、友好的错误提示 3. **保持可调试性**:开发环境下保留详细日志 ## ⚠️ 优化前的问题 ### 暴露的敏感信息 ```json { "success": false, "code": 422, "message": "body -> folderId: Input should be a valid UUID...", "data": { "errors": [ { "type": "uuid_parsing", // ❌ 暴露 Pydantic 验证类型 "loc": ["body", "folderId"], "msg": "Input should be a valid UUID, invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `v` at 1", "input": "virtual-mine", "ctx": { // ❌ 暴露内部验证上下文 "error": "invalid character: expected an optional prefix of `urn:uuid:`..." }, "url": "https://errors.pydantic.dev/2.12/v/uuid_parsing" // ❌ 暴露框架版本 } ] } } ``` ### 存在的安全隐患 - ✖️ 暴露后端使用 Pydantic 2.12 - ✖️ 暴露内部验证逻辑和规则 - ✖️ 技术术语对普通用户不友好 - ✖️ 提供了探测系统的信息 ## ✅ 优化后的响应 ### 友好的错误格式 ```json { "success": false, "code": 422, "message": "参数验证失败,共 2 个错误", "data": { "errors": [ { "field": "folderId", "message": "必须是有效的 UUID 格式,或者不传此字段" }, { "field": "plannedDuration", "message": "必须大于 0,或者不传此字段" } ] }, "timestamp": "2026-02-05T08:00:04.953349+00:00" } ``` ### 优势 - ✅ 隐藏了技术实现细节 - ✅ 提供清晰的字段名和错误说明 - ✅ 给出了解决建议("或者不传此字段") - ✅ 只返回必要的业务信息 - ✅ 更符合 RESTful API 最佳实践 ## 🔒 错误类型映射表 | Pydantic 错误类型 | 用户友好消息 | |-------------------|-------------| | `uuid_parsing` | 必须是有效的 UUID 格式,或者不传此字段 | | `greater_than` | 必须大于 {值},或者不传此字段 | | `string_too_short` | 长度不能少于 {min} 个字符 | | `string_too_long` | 长度不能超过 {max} 个字符 | | `missing` | 此字段为必填项 | | `string_pattern_mismatch` | 格式不正确 | | `value_error` | 值不合法 | ## 🛠️ 开发调试 在开发环境中(`DEBUG=True`),详细的验证错误会记录在日志中: ```log WARNING - 验证错误详情: [{'type': 'uuid_parsing', 'loc': ('body', 'folderId'), ...}] ``` 这样既保证了生产环境的安全性,又方便开发人员调试。 ## 📝 使用建议 ### 前端错误处理 ```typescript try { const response = await createProject(data); } catch (error) { if (error.code === 422 && error.data?.errors) { // 显示友好的错误提示 error.data.errors.forEach(err => { showFieldError(err.field, err.message); }); } else { showGeneralError(error.message); } } ``` ### 字段级错误提示示例 ``` 📍 folderId: 必须是有效的 UUID 格式,或者不传此字段 📍 plannedDuration: 必须大于 0,或者不传此字段 ``` ## 🔐 安全最佳实践 1. **永远不要返回**: - 内部错误堆栈信息 - 数据库错误详情 - 框架版本和类型 - 文件路径和系统信息 2. **应该返回**: - 用户可操作的错误信息 - 字段名称和位置 - 验证规则的简要说明 - 修复建议 3. **分环境处理**: - 生产环境:简洁、安全的错误消息 - 开发环境:详细的调试信息(仅在日志中) - 测试环境:保留适度的详细信息 ## 📊 错误响应示例对比 ### 单字段错误 ```json // 优化后 { "success": false, "code": 422, "message": "folderId: 必须是有效的 UUID 格式,或者不传此字段", "data": { "errors": [ { "field": "folderId", "message": "必须是有效的 UUID 格式,或者不传此字段" } ] }, "timestamp": "2026-02-05T08:00:04.953349+00:00" } ``` ### 多字段错误 ```json // 优化后 { "success": false, "code": 422, "message": "参数验证失败,共 3 个错误", "data": { "errors": [ { "field": "name", "message": "此字段为必填项" }, { "field": "folderId", "message": "必须是有效的 UUID 格式,或者不传此字段" }, { "field": "plannedDuration", "message": "必须大于 0,或者不传此字段" } ] }, "timestamp": "2026-02-05T08:00:04.953349+00:00" } ``` ## 🎯 总结 通过这次优化: - ✅ 提升了 API 的安全性 - ✅ 改善了用户体验 - ✅ 保持了开发调试的便利性 - ✅ 符合生产环境的最佳实践