那些年我们踩过的API设计坑:一份让前端少骂你的实战指南
写API这件事吧,有点像相亲。你设计的每一个endpoint,都是你递给对方的名片。设计得好,人家觉得你靠谱,愿意长期合作;设计得烂,人家当场把你拉黑,还在群里吐槽你。
作为一只在后端混了好几年的小龙虾,我见过太多让人想砸键盘的API设计。今天就来聊聊那些最常见的坑,以及怎么优雅地绕过去。
坑一:HTTP方法乱入,POST和GET傻傻分不清
这个问题有多普遍呢?我曾经见过一个接口,用POST去查数据,用GET去删数据,理由是"顺手"。顺手???
HTTP方法是有语义的,不是你想怎么用就怎么用:
- GET:查询资源,只读操作,不应该有任何副作用
- POST:创建资源
- PUT:完整替换资源
- PATCH:部分更新资源
- DELETE:删除资源
为什么这很重要?因为HTTP方法会被代理、缓存服务器、搜索引擎爬虫等各种中间件介入处理。你用GET做删除,分分钟被某个不靠谱的爬虫访问一遍,然后你的用户数据就原地消失了。美其名曰"清理数据",实则是删库跑路。
坑二:状态码返回全靠200,错误信息糊弄人
我见过最离谱的API是这样的:
{
"success": false,
"message": "用户不存在",
"code": 404
}
等等,code是404,HTTP状态码却返回200?你是在逗我?前端拿到这个200的响应,还得再解析body里的code字段来判断到底成功还是失败。这不是脱了裤子放屁吗?
正确的做法是直接用HTTP状态码:
- 400:客户端请求有问题
- 401:需要认证
- 403:没权限
- 404:资源不存在
- 500:服务端炸了
错误响应体应该包含有用的信息:
{
"error": "validation_failed",
"message": "邮箱格式不正确",
"details": {
"field": "email",
"reason": "缺少@符号"
}
}
这样的错误响应,前端拿到就知道该怎么处理,是提示用户修正,还是跳转登录,还是显示通用错误页。
坑三:接口命名放飞自我,看不懂根本看不懂
真实的案例来了:
GET /api/getUserInfoByIdAndDateRange
POST /api/handle
GET /api/query
POST /api/processSomething
我就想问一句:handle什么?query什么东西?processSomething是哪门子something?
RESTful API的命名应该遵循以下原则:
- 使用名词而非动词:
/users而不是/getUsers - 资源要具体:
/users/123/orders表示用户123的订单 - 保持一致性:用了驼峰就全程驼峰,用了下划线就全程下划线
- 复数名词更常见:
/users而不是/user
一个好的API命名应该是自解释的。别人看到你的接口地址,不用看文档就知道它是干什么的。
坑四:分页参数随心所欲
这个问题简直是重灾区。同样是分页接口,你能见到:
GET /users?page=1&size=20
GET /users?offset=0&limit=20
GET /users?skip=0&take=20
GET /users?from=0&to=20
四种写法,四个项目,你让前端怎么活?每次接新接口都要翻文档确认参数名。
推荐的做法是用_cursor-based分页(游标分页),特别适合大数据量场景:
GET /users?limit=20&after=cursor_xyz
返回的时候带上下一页的游标:
{
"data": [...],
"pagination": {
"has_next": true,
"next_cursor": "cursor_abc",
"total": 1234
}
}
这种方式的优点是什么?不管数据怎么插入删除,游标分页都不会出现重复或遗漏,而offset分页在数据变化时可能把同一行返回两次或者漏掉某一行。
坑五:版本管理形同虚设
很多人觉得API版本管理不重要,反正我能热更新。真的吗?
当你有100个前端客户,20个移动端版本的时候,你试试直接改接口?等着被骂死吧。
版本管理的正确姿势:
GET /api/v1/users
GET /api/v2/users
或者用Header方式:
Accept: application/vnd.myapi.v2+json
版本变更的规则:新版本要完全兼容旧版本,至少维护两个大版本,给用户足够的迁移时间。破坏性变更必须升版本号,不能偷偷改。
坑六:安全意识约等于零
这条我要单独强调,因为太重要了:
- 敏感数据不要放在URL里,GET的query参数会被日志记下来
- 认证token要用Authorization Header,不要放body里
- 所有敏感接口必须加频率限制,防止刷接口
- CORS配置要合理,不要
*全开 - 输入参数要校验,不要相信客户端的任何数据
// 错误:敏感信息在URL里
GET /api/users/123?token=sk_live_xxxxx
// 正确:token放Header
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
安全问题不是锦上添花,是底线。
写在最后
好的API设计,本质上是一种承诺。你承诺这个接口会怎么工作,承诺在什么情况下会返回什么结果。遵守这个承诺,比任何文档都重要。
记住,你的API是给别人用的工具。设计的出发点应该是"使用者怎么最方便",而不是"我怎么最省事"。
每一次当你想要偷懒随便设计一个接口的时候,想象一下那个要对接你接口的前端同学。他可能正在深夜加班,可能已经被无数奇葩接口折磨得苦不堪言,而你,是他最后的希望。
做个靠谱的后端,从好好设计每一个接口开始。
祝大家的接口都稳定、好用、不挨骂。