做后端开发这么多年,看过的API没有一千也有八百。有时候接别人的接口,真的想顺着网线爬过去问问ta:你写的是API还是密码学论文?
今天不整虚的,直接聊几个教科书上不会写、但实战中踩坑无数次的经验。
1. 错误处理:别让调用方猜谜
见过最多的灾难就是这个:
{
"code": -1,
"message": "操作失败"
}
操作失败是什么失败?是参数错了?是权限不够?是服务器炸了?调用方看到这条消息,只能开始猜猜猜。
我的原则:错误信息要能指导下一步行动。好的错误返回长这样:
{
"code": 10041,
"message": "手机号格式不正确,请输入11位数字",
"field": "phone",
"request_id": "req_abc123"
}
看,这才叫良心API。调用方知道是phone字段的问题,知道是格式问题,知道可以用request_id去查日志。
2. HTTP状态码:别一股脑返回200
有人喜欢所有响应都返回200,然后在body里塞code字段表示成功失败。这不叫RESTful,这叫「表面一套背后一套」。
状态码就是用来表达语义的:
- 200 - 成功,别犹豫
- 201 - 创建成功,POST资源后用这个
- 400 - 客户端参数有问题,别甩锅给服务器
- 401 - 没认证,先登录去
- 403 - 认证了但没权限,别挣扎
- 404 - 资源不存在,你找错地方了
- 500 - 服务器挂了,这个锅我们背
用对状态码,前端小哥会感谢你的。
3. 分页:别让数据库喊救命
「给我所有用户」——这句话我听过太多次,每次都血压升高。
做后端的要记住:永远不要相信「只要前10条」这种鬼话。分页不是可选项,是必选项。
GET /api/users?page=1&page_size=20
{
"data": [...],
"pagination": {
"page": 1,
"page_size": 20,
"total": 1523,
"total_pages": 77
}
}
还有,别用OFFSET分页了,数据量大的时候越往后越慢。推荐用游标分页(Cursor Pagination),基于ID或时间戳,性能稳定得一批。
4. 接口版本:给自己留条活路
接口上线了,需求改了,业务调整了——然后呢?你不能把旧接口直接干掉,几百个调用方会提着刀来找你。
版本号是护身符:
GET /api/v1/users
GET /api/v2/users
新版本做兼容,平稳过渡。实在要下线,提前三个月发通知,这是基本的江湖道义。
5. 幂等性:重试不是你崩溃的理由
网络不稳定的时候,调用方重试请求是常态。你的接口能不能扛住,这才是关键。
GET是天然幂等的,DELETE和PUT也可以设计成幂等的。POST比如「创建订单」,怎么幂等?用唯一请求ID:
headers: {
"X-Idempotency-Key": "unique_request_id_123"
}
服务器端缓存这个key的处理结果,重试时直接返回缓存,不重复扣款、不重复创建订单。皆大欢喜。
6. 文档:没有文档的API等于没有API
这不是建议,这是声明:你写了个没文档的API,跟没写有什么区别?
swagger也好,apidoc也好,postman导出也好——随便选一个,把文档写起来。request example、response example、错误码列表、认证方式,这些必须有。
我见过最离谱的API文档就一句话:「见注释」。注释呢?在代码里。代码呢?不能给你看。合着这文档是个谜语人对吧?
写在最后
写API这件事,技术门槛不高,但细节坑巨多。一个好的API,调用方用起来的感觉是「润」,像德芙一样丝滑。一个烂的API,用起来的感觉是「想砸键盘」。
想让别人觉得你靠谱?先让别人的代码别因为你的API而报错。
共勉。