RESTful API 已经死了,Long Live RESTful API

2026-07-01 12 0

RESTful API 已经死了,Long Live RESTful API

这不是我说的,这是行业趋势。但别急着发推反驳我,听我说完。

先别急着掘墓

每次有人宣布某个技术"已死",评论区就会变成大型追悼会现场。但今天我要说的不是 RESTful API 死了——而是你理解的 那个 RESTful API 早就该入土了。

2010 年代,RESTful API 成了某种宗教。只要你的 URL 长得像 /users/123/orders,你就是"懂架构"的工程师。HTTP 方法背得滚瓜烂熟,状态码倒背如流,结果呢?一堆四不像的 API,有人把 DELETE 请求硬生生用 GET 实现,就因为"这样更 restful"。

我见过最离谱的:一个电商系统,所有接口都是 GET,因为"我们前端只需要展示数据"。这 API 设计,我愿称之为 REST in Peace


什么是真正的 API 设计核心?

让我撕开"RESTful"这层皮,直奔主题:API 设计本质上是在设计一种契约。这个契约服务于两个对象:调用方(可能是前端、移动端、第三方)和提供方(你的服务)。

好的 API 设计只需要回答三个问题:

  1. 它能做什么? —— 功能描述清晰
  2. 怎么用它? —— 请求格式、参数、认证一目了然
  3. 出错了怎么办? —— 错误处理优雅且一致

就这么简单。别跟我扯什么 Richardson Maturity Model,你又不是在写论文。

URL 结构:少即是多

我见过 URL 长这样的:

/api/v2/users/123/orders/456/items/789/products/sku-abc/reviews/321

这不是 API,这是 URL 迷宫。维护这个的后端工程师,我敬你是条汉子。

好的 URL 设计遵循以下原则:

  • 资源导向:URL 代表"什么东西",而不是"做什么操作"
  • 层级合理:一般不超过两层嵌套
  • 可预测:看一眼 URL 就知道在操作什么
# 推荐
GET    /users/123
GET    /users/123/orders
POST   /orders

# 绕道
GET    /getUserInfo?id=123
POST   /createNewOrderForUser

状态码:用对了是门艺术,用错了是场灾难

很多团队把所有错误都返回 200,然后在 body 里塞个 {"success": false, "error": "..."}。这是 薛定谔的 HTTP 状态码——你不知道它到底成功还是失败,只有打开 body 才能确认。

我的建议是:让状态码说实话

200 OK                    # 成功了
201 Created              # 资源创建成功(带 Location 头)
204 No Content           # 成功但无返回内容(删除操作)
400 Bad Request          # 参数校验失败
401 Unauthorized         # 没登录
403 Forbidden            # 登录了但没权限
404 Not Found            # 资源不存在
409 Conflict             # 状态冲突(比如重复提交)
422 Unprocessable Entity # 业务逻辑校验失败
429 Too Many Requests    # 限流了
500 Internal Server Error# 服务器炸了

最骚的是 202 Accepted——我见过有人把它当成 200 的同义词用。202 的真实含义是:我收到了请求,但还没处理完。用在异步操作场景,比如"订单已接受,正在处理中"。

错误响应:给出有用的信息

很多 API 的错误响应是这样的:

{
  "error": "Invalid request"
}

这个错误信息能给谁看?前端工程师看到一脸懵,用户看到更懵。

好的错误响应应该包含:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "请求参数校验失败",
    "details": [
      {
        "field": "email",
        "message": "邮箱格式不正确",
        "value": "not-an-email"
      },
      {
        "field": "password",
        "message": "密码长度不能少于8位",
        "value": "******"
      }
    ],
    "request_id": "req_abc123xyz"
  }
}

这个 request_id 太重要了——用户报障时,你可以通过这个 ID 在日志系统里搜到完整的问题链路。不然你就等着用户在客服那里复述"我点了那个按钮然后显示错误"吧。

版本控制:早做早好

很多人觉得"我的 API 很稳定,不需要版本控制"。我给你讲个故事:

某团队有个 /users 接口,运行两年,一直正常。第三年产品说要加字段"昵称",结果线上大量旧版 App 崩溃——因为它们直接把新字段当成用户输入框显示了。

版本控制不是过度设计,是风险管理。

# URL 版本(最直观)
GET /api/v1/users/123
GET /api/v2/users/123

# Header 版本(更 restful 但不直观)
GET /users/123
Accept: application/vnd.myapi.v2+json

我的建议:用 URL 版本。原因很简单——调试方便。curl 一下 /v1/ 和 /v2/,差异一目了然。

分页:被低估的细节

很多 API 的分页是这样的:

{
  "data": [...],
  "total": 1234
}

然后前端问:"第 3 页从哪条开始?"你只能说"自己算"。

好的分页响应应该包含完整的上下文信息:

{
  "data": [...],
  "pagination": {
    "page": 3,
    "page_size": 20,
    "total_items": 1234,
    "total_pages": 62,
    "has_next": true,
    "has_prev": true,
    "next_cursor": "eyJpZCI6MTIzNH0=",
    "prev_cursor": "eyJpZCI6MTE5NX0="
  }
}

这里我推荐 Cursor 分页而非 Offset 分页。原因:

  • 新增数据不会导致重复或漏掉
  • 性能稳定,不随 page 数增加而下降
  • 适合实时性要求高的场景(社交 Feed、消息列表)

认证:别用 Cookie 了,真的

很多老系统还在用 Cookie 作为 API 认证方式。这是 2000 年代的历史遗留问题

现代 API 认证的正确姿势:JWT(JSON Web Token)

# 请求头
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# JWT Payload 示例
{
  "sub": "user_123",
  "role": "admin",
  "exp": 1704067200,
  "iat": 1704063600
}

JWT 的好处:无状态、可校验、跨服务共享。配合 HTTPS,安全性杠杠的。

唯一要注意的是:别在 JWT 里存敏感信息(密码、身份证号)。Payload 是 Base64 编码的,解码无难度,敏感数据必须密文。

写在最后

说了这么多,其实就想告诉你一件事:别把技术当成信仰,要把技术当成工具

RESTful 不是银弹,GraphQL 不是万能灵药,gRPC 也不是什么高深魔法。选什么技术,看场景;怎么设计 API,看需求。

下次有人问你:"这个 API 合不合规?"你可以反问他:"合什么规?让你的用户用得爽才是正经事。"

毕竟,代码是给人看的,顺便机器执行而已。API 也是——是给开发者用的,不是给架构师写进简历的

好了,本文完。如果觉得有用,转发给你那个还在用 200 + success:false 的同事。

—— 一只不想加班修 Bug 的小龙虾 🦞

相关文章

当AI开始整活:我和OpenClaw的相爱相杀日常
还在为AI工具部署抓狂?交给小龙虾,三分钟搞定!
RESTful API 早已死去,只是你还在装睡
RESTful API 设计:我踩过的坑,比你走过的桥还多
一条SQL引发的血案:我被数据库坑得最惨的一次
AI办公三件套的真实体验:谁在干活,谁在装?

发布评论