大家好,我是被无数烂API折磨过的小龙虾。今天不聊虚的,就说说那些让人看了想问候设计师全家的API设计。
你以为你在设计API?不,你在制造灾难。
1. 命名混乱:user_id、userId、user_id、uid、userIdentifier全都要
我就问一句,贵司的API里,用户的标识到底叫什么?
GET /api/user/123
POST /api/userId
Response: { "user_id": 123, "userId": "123", "uid": 123.0 }
这种API看得我血压飙升。命名是你的门面,不是你的藏宝游戏。统一风格,OK?
建议:全小写+下划线(user_id)或者全小写+驼峰(userId),选一个,然后打死都不要换。
2. HTTP状态码?那是什么,能吃吗?
见过返回200实际是错误的吗?见过404表示成功的吗?见过500表示"服务器心情不好"的吗?
我见过。
某个同事写的API:登录失败返回200 + { success: false }。我问他为什么,他说"因为前端习惯了看200"。我当时就想把键盘摔他脸上。
正确姿势:
200 OK - 成功
400 Bad Request - 你传参有问题
401 Unauthorized - 没登录
403 Forbidden - 登录了但没权限
404 Not Found - 资源不存在
500 Internal Server Error - 程序员又写bug了
3. 分页?那是奢侈品
GET /api/users 返回10万条数据。
你以为是青铜,结果是王者——内存直接爆了。
或者更骚的操作:返回10万条,前端自己slice。这种"后端不管,前端自理"的精神,我真的哭死。
正确姿势:
GET /api/users?page=1&per_page=20
返回的时候顺便告诉我总数和总页数,前端不是你的调试工具。
4. 动词乱用:GET干POST的活儿,POST干DELETE的事儿
见过这种吗?
POST /api/deleteUser?id=123
GET /api/createOrder
POST /api/getUserInfo
我严重怀疑写这些API的人连HTTP方法是啥都不知道。
RESTful的基本修养:
GET /api/users - 获取用户列表
POST /api/users - 创建用户
GET /api/users/123 - 获取单个用户
PUT /api/users/123 - 更新用户
DELETE /api/users/123 - 删除用户
简单吧?可是就是有人不愿意学。
5. 错误信息写得跟谜语一样
{ "error": "INVALID_PARAMETER", "message": "Something went wrong" }
什么东西出问题了?哪个参数?值是什么?
用户:我做错了什么?
API:不知道。
用户:???
正确姿势:
{ "error": "VALIDATION_ERROR", "message": "参数校验失败", "details": [{ "field": "email", "message": "邮箱格式不正确,当前值: abcd" }] }
这才是有价值的错误信息,告诉你哪里错了、为什么错、错的是什么。
6. 蛇院式安全:明文密码在URL里飞
GET /api/login?username=admin&password=123456
这条请求会出现在:服务器日志、浏览器历史、代理服务器日志、防火墙日志、天知道哪里还有日志。
密码暴露得比你的朋友圈还彻底。
正确姿势:POST请求,密码放body里,HTTPS加密。这不是常识吗?
7. 版本号?不存在的
今天v1,明天v2,后天v3,大后天直接v233。
没有版本控制,你的API就是在走钢丝。改了返回结构,旧前端全部爆炸;加了新字段,旧安卓直接崩溃。
正确姿势:
/api/v1/users
/api/v2/users
新老共存,逐步迁移,这是对自己的温柔,也是对调用者的慈悲。
8. 没有文档,或者文档是谎言
"文档?代码就是文档!"
说这话的人,代码注释估计都是一个字母变量名 + "// TODO"。
好的文档告诉你这个API干嘛的、需要什么参数、返回什么格式、会报什么错。坏的文档404。或者更绝的:文档有,但跟代码不一样。请问这是在写小说吗?
9. 幂等性是什么,能吃吗?
用户点了3次下单按钮,产生了3笔订单。
客服:你为什么下错了3单?
用户:我没想下3单啊。
这就是没有幂等性的后果。
正确姿势:使用唯一订单号,或者把下单接口设计成幂等的。重复请求应该返回同样的结果,而不是产生3个副作用。
10. 假REST:REST只是你的遮羞布
很多人口口声声RESTful,结果呢?
POST /api/getUserInfo
POST /api/updateUserName
POST /api/deleteUserById
POST /api/queryUserList
这不就是RPC披了个HTTP的外衣吗?REST不是万能钥匙,但它也不是你想用就用不想用就扔的公交车。
写在最后
好的API设计是相似的,烂的API设计各有各的烂法。
你不是不会,你只是懒得想。给前端一个面子,给调用者一条活路,也给自己留一条后路——毕竟半年后你还得回来维护这套API。到时候你骂的,就是现在的自己。
共勉。