如果你干过后端开发,你一定有过这种经历:接手一个祖传API项目,文档写得跟情书似的朦胧,前任写的接口行为跟谜语人似的,连调试都要靠玄学。今天我就来盘点一下那些让人血压飙升的API设计骚操作,给大家乐呵乐呵,也给自己提个醒——别成为那个被后代骂的祖宗。
一、HTTP方法乱用:POST和GET傻傻分不清
有人写删除接口用POST,有人写查询用PUT,RESTful规范在他们眼里就像前女友的生日——知道有这么个东西,但就是不想记。
// 某位鬼才工程师的删除操作
POST /api/user/delete?id=123
// 某位鬼才工程师的查询
GET /api/user/update?id=123
// 还有更离谱的——用HEAD查数据
HEAD /api/article/info?id=456
兄弟们,HTTP方法是有语义的啊!GET查,POST增,PUT改,DELETE删,记住了吗?没记住的建议把手指头剁了重练。
二、命名随心所欲:接口命名玄学大赛
来看看这些接口名,你能猜到它们是干嘛的吗?
/api/getData(通用getdata,什么数据?数据库里捞的吗?)
/api/abc(abc是什么?AirBud Challenge吗?)
/api/doSomething(做点什么事?量子力学吗?)
/api/handle(处理?处理什么?处理婆媳关系吗?)
/api/manager(经理?你是让我找你们领导吗?)
/api/system(系统?你这接口是系统自带bug吗?)
好的API命名应该像好的简历——一目了然,看了就知道是干嘛的。推荐用资源+动作的命名方式,比如/api/users/{id}、/api/orders/{id}/cancel。清晰的名字是给调用者最好的礼物。
三、状态码随便返回:200表示一切安好?不一定
见过最离谱的API是这样的:业务逻辑报错,数据库挂了,磁盘满了——统统返回200 OK,然后在body里塞个{"code": 500, "message": "服务器冒烟了"}。这是200还是200你妈?
HTTP状态码是有明确含义的:
- 2xx:成功了,正常搞
- 3xx:走错路了,重定向吧
- 4xx:客户端你有问题,400到418随便挑一个
- 5xx:服务端我拉胯了,但我不说
业务错误码和HTTP状态码是两码事,别混为一谈。参数校验失败——400。认证失败——401。权限不足——403。资源不存在——404。服务器爆炸——500。这些是基本礼仪,不接受反驳。
四、返回格式看心情:JSON还是XML还是纯文本?随缘
某些API的响应格式是这样的:成功时返回JSON,失败时返回XML,某些特殊情况下返回纯文本,遇到心情不好的时候返回HTML报错页面。这哪是API,这分明是性格测试——调用方得先猜猜今天服务器心情如何。
规范的做法:
// 统一响应格式
{
"code": 0,
"message": "操作成功",
"data": {
// 实际数据
},
"timestamp": 1751257200
}
// 或者用更现代的方式
{
"success": true,
"data": {},
"error": null
}
Content-Type也要设对,JSON就是application/json,别整那些花活。
五、无限嵌套的JSON:当你凝视深渊,深渊也在凝视你
返回数据结构是这个画风:
{
"data": {
"result": {
"info": {
"list": [
{
"items": [...],
"extra": {
"details": {
"sub": {
"value": "终于找到我要的数据了"
}
}
}
}
]
}
}
}
}
// 调用方代码
const value = response.data.result.info.list[0].extra.details.sub.value;
这是返回数据还是套娃?5层嵌套起步,调个接口跟考古似的,每挖一层都能发现新大陆。建议:嵌套不超过3层,需要深度数据的场景走单独接口。
六、分页?不存在这个概念
有些API一次返回全表数据,美其名曰「减少网络请求」。结果数据库有100万条记录,接口返回100万条JSON,内存爆了,网关崩了,调用方哭了,问:为什么不加分页?答:没想过这个问题。
分页是后端的基本素养:
GET /api/articles?page=1\&page_size=20
// 返回
{
"data": [...],
"pagination": {
"page": 1,
"page_size": 20,
"total": 10000,
"total_pages": 500
}
}
这里推荐用游标分页(cursor-based pagination),比偏移量分页(offset-based)性能好很多,尤其数据量大的场景。偏移量分页在深层页码时越来越慢,游标分页始终如一,这才是正经人的选择。
七、接口不带版本:v1、v2都是浮云
好一点的API会加个版本号前缀,敷衍一点的连这个都没有。问题是业务在演进,接口要升级,但旧接口还有人在用——这时候没版本管理的话,改动就是踩雷。
// 正确的版本管理
GET /api/v1/users/123
GET /api/v2/users/123
// 或者用Header
API-Version: 2024-01-01
版本管理不只是加个v1、v2那么简单,它意味着你要有向后兼容的觉悟,或者有平滑过渡的方案。没有版本管理的API就像没有刹车系统的跑车——开起来很爽,出事的时候很惨。
八、安全?什么是安全?
有些API完全没有鉴权,或者鉴权形同虚设。URL里带明文密码,token直接放GET参数里,接口没有频率限制等着被人刷,服务端SQL拼接直接上——这不是API,这是CTF大礼包,等着黑客来挑战。
基础安全检查清单:
- 所有接口走HTTPS,这是底线
- 认证token放Authorization Header,不是URL参数
- 输入参数严格校验,防SQL注入和XSS
- 接口做频率限制,防刷防DDoS
- 敏感数据要脱敏,别把密码hash也返回
- 用OAuth 2.0或JWT,别自己造轮子
写在最后
好的API设计就像好的相声——有铺垫,有笑点,有节奏,调用方用着舒服,你改着也轻松。坏的API各有各的烂,但归根结底都是同一个问题:没站在调用方的角度想过。
下次设计API的时候,想象一下调用你接口的是一个暴躁老哥,他凌晨三点被生产问题叫醒,面对你的接口调不通——这时候你希望他看到的是什么样子的?
希望大家的接口都是那种让调用方想给你买咖啡的类型,而不是那种让人想顺着网线过来打你的类型。共勉。