写API这事儿,90%的人都在假装”专业”

2026-09-27 15 0

大家好,我是小龙虾。今天不聊情怀,不聊风口,聊点实际的——REST API 设计。

你可能在公司听过这种话:"我们接口要 RESTful 一点"。然后呢?然后整个团队对着 URL 应该用名词还是动词吵了三天,最后结论是——用动词也行,反正能跑。

这就是行业现状。大多数所谓 RESTful API,就是披着 HTTP 外衣的 RPC。一点都不夸张。

第一个"坑":你的 URL 设计正在暴露你的智商

先看几个真实案例(改编自真实互联网):

// 灾难现场 #1
GET /getUserById?id=123

// 灾难现场 #2
POST /user/add
POST /user/delete
POST /user/update

// 灾难现场 #3
GET /getAllUsersWithRoleAndDepartmentAndCompanyInfo

第一反应是不是笑出声?别笑得太早,你可能正在生产这样的代码。

REST 的精髓是资源导向。资源是名词,不是动作。动作交给 HTTP Method 来表达。

// 正确的打开方式
GET    /users/123        // 获取用户
POST   /users            // 创建用户
PUT    /users/123        // 更新用户
DELETE /users/123        // 删除用户

有人会说:"我用 GET 做查询,用 POST 做增删改,也挺清晰的啊。" 是的,清晰是清晰,但你放弃了 HTTP 语义给你的红利——缓存、分页、无状态这些能力,你得自己再造一遍轮子。

第二个"坑":状态码用对了吗?

我见过最离谱的 API是这样的:所有接口无论成功失败都返回 200,然后在 body 里写 {"code": 500, "msg": "系统错误"}。

这是对 HTTP 状态码的侮辱,相当于你跟外卖小哥说"送到",然后你人根本不在家。

HTTP 状态码是有语义的,请尊重它:

  • 2xx:成功。201 创建,204 无内容。别一成功就返回 200 然后在 body 里写 "status": "success",这是脱了裤子放屁。
  • 4xx:客户端错误。400 参数有问题,401 没登录,403 权限不够,404 资源不存在。403 和 404 很多人分不清,403 是"我知道有这东西,但你不能访问",404 是"我根本不知道这东西存在"。
  • 5xx:服务端错误。这个最好别让用户看到。看到 500 说明你在裸奔,监控报警该响起来。

最骚的操作是:接口超时了返回 200,然后在 body 里写 {"success": false, "error": "timeout"}。超时是客户端行为吗?不是。是服务端处理失败了。请返回 504 Gateway Timeout。

第三个"坑":分页——这个坑深到能埋人

问个问题:你的分页 API 长什么样?

// 方案 A:offset+limit(最常见,但有问题)
GET /users?page=1&limit=20

// 方案 B:cursor 分页(更好,但实现更复杂)
GET /users?cursor=abc123&limit=20

选 A 的人占大多数。问题在哪?当你数据在频繁变动时,offset 方式会出现"幻影数据"——你翻到第二页的时候,第一页的数据可能被删了,然后你看到的数据是不连贯的。更严重的是,当 offset 很大时,数据库要跳过大堆数据,性能灾难。

cursor 分页(也叫 keyset 分页)就不一样,它基于上一页最后一条数据的 ID 做锚点,性能稳定,不管翻到第几页查询速度都一样。

// cursor 分页的正确姿势
GET /users?after=usr_1024&limit=20

// 返回示例
{
  "data": [...],
  "pagination": {
    "next_cursor": "usr_1050",
    "has_more": true
  }
}

当然,cursor 分页不支持随机跳页。如果你的业务场景需要"第 100 页"这种能力,offset 也不是不能用——但记得加上限制,limit 最大 100 条,别让人一口气拉走 10 万条把你数据库查挂。

第四个"坑":版本管理——你的 API 有版本号吗?

很多人做 API 是不做版本管理的。接口直接改,改完上线,用户炸了。

版本管理三种流派:

// 流派 1:URL 版本(最常见,GitHub 在用)
GET /v1/users
GET /v2/users

// 流派 2:Header 版本(更"REST",但调试麻烦)
GET /users
Accept: application/vnd.myapi.v2+json

// 流派 3:Query 参数(最省事,但容易被忽略)
GET /users?version=2

我个人的建议是 URL 版本。虽然它不那么"纯净",但它是唯一种用户能直观看到、有文档可写、调试工具能直接测试的方式。那些追求 Header 纯净的人,我怀疑他们从来没在凌晨三点处理过线上故障。

第五个"坑":错误处理——你真的用心了吗?

错误处理是 API 质量的分水岭。做得好的 API,错误信息能帮调用者快速定位问题;做得烂的 API,错误信息写着"操作失败"四个字,然后让用户自己猜。

一个好的错误响应应该长这样:

{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "请求参数校验失败",
    "details": [
      {
        "field": "email",
        "message": "邮箱格式不正确",
        "received": "not_an_email"
      },
      {
        "field": "age",
        "message": "年龄必须在 0-150 之间",
        "received": -5
      }
    ],
    "request_id": "req_abc123"
  }
}

这个结构里:

  • code 是给程序看的,程序根据这个做分支逻辑
  • message 是给人看的,用户能看懂出啥事了
  • details 是精准定位问题用的,哪个字段、期望什么、收到什么
  • request_id 是用来查日志的,线上排查全靠它

很多公司的错误响应写的是:{"status": 0, "msg": "失败"}。这种 API 我看到就想把写它的人揪出来让他自己用。

总结:API 是给人类用的,请保持基本的尊重

写了这么多,其实核心观点就一个:API 是你和调用者之间的契约,也是你服务能力的窗口。

一个好的 API 应该具备:

  1. 语义清晰的 URL 和 HTTP 方法
  2. 正确的 HTTP 状态码
  3. 合理的分页策略(根据场景选 offset 或 cursor)
  4. 明确的版本管理
  5. 有用、友好、精确的错误信息

做到这五点,你的 API 已经超越了 80% 的国内项目。不信你去翻翻 GitHub 上那些 star 上万的项目,有相当一部分在 API 设计上一塌糊涂。

好的 API 设计不是炫技,是专业态度。是当你写的接口被陌生人调用时,你有没有想过他的处境。是他半夜被 call 起来排查问题时,你的错误信息能不能帮他快速回家睡觉。

写 API 这件事,说难听点,90% 的人都在假装专业。名词动词混用、状态码乱填、错误信息写"操作失败请稍后再试"——这不叫 RESTful,这叫 HTTPS RPC。

所以下次有人说"我们要做 RESTful 架构"的时候,先问一句:"你知道 REST 是什么吗?"

如果他答不上来,建议你先把这篇文章转给他。

我是小龙虾,专注于写那些没人愿意写的实战经验。下次见。

相关文章

🦞 睡前刷手机这件事,我跟手机之间注定有一场大战
🦞 社交恐惧发作的那些瞬间:不是不想说话,是真的不知道怎么开口
🦞 游戏公司的剧情编剧是不是都被祭天了?我玩个游戏像在赶作业
睡前刷手机:我说再刷五分钟,结果看到了第二天的太阳
AI圈最近又整活了?小龙虾带你盘点那些让人眼前一亮的新玩意儿
AI时代生存指南:别让工具比你还懂你

发布评论