
开篇
上一篇文章,我们用 AI 搭出了任务清单 API 的第一版骨架。
服务能启动,并不代表接口已经设计完成。真正开始联调后,下面这些问题很快就会出现:
- 创建任务失败时,返回什么结构?
- 任务不存在时,是返回空对象还是 404?
PATCH可以修改哪些字段?- 参数错误和服务器错误,调用方如何区分?
今天就解决这两个问题:
text
明确接口契约
↓
统一成功响应
↓
统一异常响应
↓
用边界请求验证
一、先让 AI 识别接口设计缺口
不要直接问 AI"帮我完善接口",先把已有约束交给它,让它找缺口:
text
请审查下面的任务清单 API 设计,先不要写代码。
已有接口:
- GET /api/tasks:查询任务列表
- POST /api/tasks:创建任务
- PATCH /api/tasks/:id:修改任务状态
- DELETE /api/tasks/:id:删除任务
任务字段:id、title、completed、createdAt。
数据暂时保存在内存中。
请重点检查:
1. 每个接口的参数和返回值是否明确。
2. HTTP 状态码是否合理。
3. 参数错误、资源不存在和服务器异常如何区分。
4. PATCH 是否可能修改不允许的字段。
5. 是否存在成功但数据没有真正改变的情况。
请输出:设计缺口、推荐约定、待确认问题。
确认前不要生成代码。
AI 适合帮助我们找遗漏,但接口最终约定必须由开发者确认,不能直接采用它的默认习惯。
二、先确定一份接口契约
我会先把四个接口约定成下面这样:
| 接口 | 成功状态 | 成功结果 | 主要失败状态 |
|---|---|---|---|
GET /api/tasks |
200 | 任务数组 | 500 |
POST /api/tasks |
201 | 新任务对象 | 400、500 |
PATCH /api/tasks/:id |
200 | 修改后的任务 | 400、404、500 |
DELETE /api/tasks/:id |
204 | 无响应体 | 400、404、500 |
这里有两个容易被忽略的约定:
- 创建资源使用
201,而不是所有成功请求都返回200。 - 删除成功使用
204,响应体为空,调用方不需要再解析 JSON。
PATCH 只允许修改 completed:
json
{
"completed": true
}
客户端不能通过 PATCH 修改 id、createdAt 或 title。如果后续要支持修改标题,可以单独扩展契约,不要让接口默默接受任意字段。
三、统一异常响应结构
如果每个路由返回不同格式,前端和调用方就需要写很多特殊判断。
我会统一使用下面的错误结构:
json
{
"error": {
"code": "TASK_NOT_FOUND",
"message": "任务不存在",
"requestId": "req_123456"
}
}
三个字段分别表示:
code:稳定的业务错误标识,程序根据它处理分支。message:给开发者或用户看的说明,不建议作为程序判断条件。requestId:方便根据一次请求查找服务端日志。
常见错误可以先约定为:
| 状态码 | code | 适用场景 |
|---|---|---|
| 400 | INVALID_TITLE |
标题为空或类型错误 |
| 400 | INVALID_STATUS |
completed 不是布尔值 |
| 404 | TASK_NOT_FOUND |
任务不存在 |
| 500 | INTERNAL_ERROR |
未预期的服务异常 |
不要把堆栈信息、数据库错误或内部路径直接返回给调用方。开发细节应该写入服务端日志。
四、让 AI 按契约补齐代码
接口约定确认后,再让 AI 修改代码:
text
请根据已经确认的接口契约修改 task-api。
要求:
1. POST 成功返回 201,DELETE 成功返回 204。
2. POST 只接受非空字符串 title。
3. PATCH 只允许修改 completed,且必须是布尔值。
4. 任务不存在时返回 404 和 TASK_NOT_FOUND。
5. 参数错误时返回 400,并使用统一 error.code 结构。
6. 未捕获异常统一返回 500 和 INTERNAL_ERROR。
7. 不把错误堆栈返回给客户端。
8. 保持现有目录结构,不新增第三方依赖。
请先列出准备修改的文件和修改原因,再输出代码。
这个 Prompt 有两个关键点:
- 把状态码、字段和修改范围写成明确约束。
- 要求 AI 先列修改文件,避免它顺手重构整个项目。
五、用边界请求验证异常处理
接口设计不能只用一个成功请求证明。至少执行下面几组验证:
创建空标题:
bash
curl -i -X POST http://localhost:3000/api/tasks \
-H "Content-Type: application/json" \
-d '{"title":""}'
预期结果:状态码 400,错误码为 INVALID_TITLE。
修改不存在的任务:
bash
curl -i -X PATCH http://localhost:3000/api/tasks/999 \
-H "Content-Type: application/json" \
-d '{"completed":true}'
预期结果:状态码 404,错误码为 TASK_NOT_FOUND。
尝试修改不允许的字段:
bash
curl -i -X PATCH http://localhost:3000/api/tasks/1 \
-H "Content-Type: application/json" \
-d '{"id":99,"completed":true}'
预期结果应该提前约定:拒绝非法字段,或者忽略非法字段,但不能悄悄修改 id。
删除成功后再次查询:
bash
curl -i -X DELETE http://localhost:3000/api/tasks/1
curl -i http://localhost:3000/api/tasks/1
预期结果:第一次返回 204,第二次返回 404。
六、我会特别检查的 4 个坑
1. 错误状态码全部返回 200
这会让调用方无法通过 HTTP 状态快速判断请求是否成功,也会影响监控和重试策略。
2. 错误信息不稳定
如果前端根据中文 message 判断错误,文案一改就可能导致逻辑失效。程序判断应该使用稳定的 code。
3. PATCH 接受整个对象
直接把请求体合并到任务对象,可能导致客户端覆盖 id、创建时间等只读字段。
4. 捕获异常后只返回"请求失败"
用户得到的信息太少,开发者也无法排查。响应中保留 requestId,服务端日志记录完整上下文,才形成可排障闭环。
七、Day 23 的验收清单
text
[ ] 四个接口的成功状态码已经确定。
[ ] 参数、返回值和可修改字段已经写清楚。
[ ] 所有错误响应使用统一结构。
[ ] 参数错误、资源不存在和服务异常能够区分。
[ ] 不会把内部堆栈返回给客户端。
[ ] 已用成功请求和边界请求分别验证。
[ ] 接口约定已经同步到 README 或接口文档。
今天完成的不是"让代码更复杂",而是让调用方知道:成功时会得到什么,失败时应该怎么处理。
总结
让 AI 补齐 API 设计和异常处理,可以遵循下面的顺序:
text
先找设计缺口
↓
确认接口契约
↓
统一错误结构
↓
限制修改范围
↓
用边界请求验收
- 接口设计先确定状态码、参数和返回结构。
- 错误响应要有稳定的错误码,不能只返回一句模糊提示。
- 让 AI 先说明修改文件和原因,再生成代码。
- 成功流程和失败流程都要实际验证。
下一篇文章,我们将继续给这个项目补上测试:
《小项目实战 3:用 AI 设计测试用例并发现隐藏 Bug》
✍坚持原创,求关注,点赞,收藏