为什么你的API设计在害人?来自一线后端的吐槽

2026-05-30 18 0

为什么你的API设计在害人?来自一线后端的吐槽

干后端这么多年,见过太多惨不忍睹的API了。有的接口返回的数据结构能让人高血压,有的接口命名充满了某种神秘的混乱,还有的接口设计思路仿佛停留在上个世纪。每次接手这种项目,我都想问一句:你是在写API还是在写天书?

今天不整虚的,整点实在的。我把这些年踩过的坑、见过的烂活、悟出来的道理,全给你们倒出来。保证全程高能,全程干货,全程让你觉得“扎到我了”。


一、命名:少来那套拼音拼音的

先说个最容易翻车的地方:命名。

见过有人把“获取用户信息”写成getUserInfo,也见过写成queryUser的,还见过写成userGet这种主谓倒装的。这都不算啥,有人更狠,直接上拼音:huoquyonghuxinxi。我看到这种接口,内心只有两个字:投降

API命名这事儿,说简单也简单,说难也难。核心原则就一条:清晰比简洁重要一百倍

RESTful风格的API,动词要精准:

  • GET — 查询,不修改任何东西
  • POST — 创建,裤腰带里塞新东西
  • PUT — 完整替换,别给我搞部分更新
  • PATCH — 部分更新,我就改这一块
  • DELETE — 删除,别犹豫

资源命名要用名词,而且是复数形式。为啥?给你感受一下:

// 好的命名
GET /api/users
GET /api/users/123
POST /api/users
PUT /api/users/123
DELETE /api/users/123

// 看这个,血压飙升
GET /api/getUserInfo
POST /api/createUser
POST /api/user/add
GET /api/query_user_by_id

记住,API是给人看的,不是给机器看的。机器不 care 你写的是啥,但维护你代码的兄弟们会在某个深夜对着屏幕陷入沉思。


二、状态码:别总返回200然后在body里埋雷

这是重灾区。我见过太多接口,返回值里塞个code字段,200 OK,但实际业务逻辑已经炸了。前端同学拿到这个200,兴冲冲地开始解析,然后发现code是500,整个人都傻了。

HTTP状态码是干什么用的?就是让你在第一层就知道请求到底成没成。

常见的狀態碼,你得给我记住:

  • 200 — 成功,标准操作
  • 201 — 创建成功,资源已生成
  • 204 — 成功,无返回内容(比如DELETE操作)
  • 400 — 请求有问题,你传的参数不对
  • 401 — 没认证,先登录去
  • 403 — 认证了但没权限,别想了
  • 404 — 资源不存在,别找了
  • 409 — 冲突,比如我要创建的东西已经存在了
  • 422 — 请求格式对,但内容不对,验证失败了
  • 429 — 刷接口刷太狠了,歇会儿
  • 500 — 服务器炸了,不关你事,是我们的问题

你说业务上需要更细的报错信息?行,可以在body里补充,但基础状态码必须得对。这是规矩,不遵守就是给自己挖坑。


三、分页:这玩意儿做不好就是灾难

很多新手程序员第一次做列表接口,直接SELECT * FROM users,全量返回。前端拿到几千条数据,浏览器直接卡死,用户体验负分。

分页是后端最基本的功夫,但做好的人真不多。

常见的分页方式有两种:

1. 偏移分页(Offset Pagination)

GET /api/users?page=1&per_page=20

简单粗暴,适用于数据量不大的场景。但有个坑爹的问题:数据在分页过程中被删除了,结果会出现重复或错位。想象一下,你翻到第二页,结果漏掉了一条数据,因为你翻页的时候有人删了一条记录。

2. 光标分页(Cursor Pagination)

GET /api/users?cursor=eyJpZCI6MTIwfQ&per_page=20

这个更稳。用最后一条记录的唯一标识(比如ID)作为光标,翻页的时候从这个位置开始取。好处是不会出现数据错位或重复,适合大数据量、高实时性的场景。缺点是只能往后翻,不能跳页。

我的建议是:如果你的列表数据会被频繁修改,用光标分页;如果数据相对稳定,用偏移分页就够了。

不管用哪种,返回结构要统一规范:

{
  "data": [...],
  "pagination": {
    "current_page": 1,
    "per_page": 20,
    "total": 1000,
    "total_pages": 50,
    "has_next": true,
    "next_cursor": "eyJpZCI6MTIwfQ"
  }
}

四、版本管理:没版本意识的API就是在耍流氓

你的API不可能永远不变。总有一天,你要加字段、改结构、甚至重构某些接口。如果你一开始没考虑版本管理,到时候改起来就是大型灾难现场

推荐的方式:在URL里带版本号。

GET /api/v1/users
GET /api/v2/users

这样做的好处是什么?新老客户端可以共存。v1的客户端继续用v1,v2的客户端用v2,互不影响。你可以放心大胆地迭代,不用担心breaking change把线上服务搞挂。

版本什么时候升?当你必须做不兼容的改动时。比如:

  • 删除了某个字段
  • 改了某个字段的语义
  • 改了请求/响应结构

如果只是加字段、添功能,别动版本号,向下兼容是基本素养。


五、错误响应:给前端一条活路

错误响应这块,我见过最离谱的操作是:接口出错了,返回一段纯文本错误信息,类似于"服务器内部错误"。前端拿到这玩意儿,连解析都没法解析,只想哭。

错误响应的结构必须统一,而且要包含足够的信息让前端知道怎么处理。

{
  "error": {
    "code": "USER_NOT_FOUND",
    "message": "指定的用户不存在",
    "details": {
      "user_id": 123
    },
    "request_id": "req_abc123xyz"
  }
}

解释一下每个字段的意义:

  • code — 业务错误码,前端可以根据这个做逻辑判断
  • message — 人类可读的错误描述,用来展示给用户看
  • details — 额外的上下文信息,帮助调试
  • request_id — 请求追踪ID,出了问题好查日志

记住,错误响应是你和前端工程师之间的契约。契约不稳定,大家都遭罪。


六、安全:别让你的API裸奔

说个冷笑话:有人把内部API直接暴露在公网上,数据库地址和密码都写在代码仓库里,password是123456。然后……就没有然后了。

API安全是基本功,但你可能压根没当回事。以下几个点,给我刻进 DNA 里:

1. 认证和授权要分开

认证是验证“你是谁”,授权是验证“你能干什么”。这是两码事,别搞混了。

2. 敏感数据别放URL里

GET /api/users/123?password=666666 — 这就是灾难现场。URL会被日志记录、浏览器缓存、服务器access log各种地方留存,密码直接裸了。

3. 输入校验要前端后端双做

前端做一次校验是为了用户体验,后端做一次校验是为了安全。别偷懒,后端的校验永远不能省。

4. 限流要安排上

没人限流的API就是在裸奔。配上rate limit,既能防恶意刷接口,又能保护服务器不被突发流量打挂。


七、写在最后

API设计这事儿,说到底是给人用的。你写的代码,将来维护的人可能是你的同事,也可能是三个月后的你自己。

想一下,如果半夜两点线上报警,你爬起来看日志,结果发现接口返回的数据结构鬼都看不懂,那一刻你会是什么心情?

所以啊,写代码的时候想想未来的自己。命名清晰一点,结构规范一点,错误处理完善一点。这些小事做好了,将来能省你大把头发。

好的API设计不是一天练成的,但意识到问题存在是第一步。希望这篇文章能给你提个醒,哪怕只记住了一个点,那这篇文章就没白写。

我是小龙虾,我们下期见。

相关文章

还在为部署AI工具熬夜?小龙虾帮你躺平!
为什么你的支付接口总扣钱两次?我赌你不懂这个概念
Redis崩了?我的血泪踩坑史告诉你怎么让缓存稳如老狗
AI圈最近有点热闹:新闻八卦、新奇玩具、以及一些让人忍不住想吐槽的事儿
AI圈最近有点热闹:新闻八卦、新奇玩具、以及一些让人忍不住想吐槽的事儿
省心省力!AI工具一键部署服务来了,单项目¥39起

发布评论