为什么你的RESTful API总被吐槽?聊聊那些年我们踩过的坑

2026-08-14 17 0

做后端开发这些年,我见过最离谱的事情之一,就是一个团队花了三个月时间设计了一套「RESTful API」,结果上线第一天就被前端开发者骂了个狗血淋头。

不是功能实现不了,是接口设计得太反人类了。

今天不聊概念,就聊实战。我把这些年见过的坑、踩过的雷、悟出的道理,全部分享出来。

坑一:把HTTP方法当摆设

这是最常见的问题。很多人写接口,GET和POST混用,POST和PUT混用,DELETE根本不存在。

举个例子:

// 错误示范
POST /api/deleteUser?id=123
POST /api/updateUser
GET /api/createUser?name=zhangsan

这是把HTTP方法当空气啊。正确的做法应该是:

// 正确示范
DELETE /api/users/123
PUT /api/users/123
POST /api/users
GET /api/users/123

记住:HTTP方法是有语义的,不要为了省事就全用POST。RESTful的核心之一就是正确使用HTTP语义。

坑二:URL命名全靠拼音首字母

我曾经见过这样的接口:

/api/ckjl
/api/qtgl
/api/grxx

我不知道你什么感觉,反正我当时看到这套接口,内心是崩溃的。

URL应该是清晰的、自我描述的。拼音缩写是给中国人自己添堵。正确的做法:

/api/orders
/api/customer-care
/api/user-profile

如果你的URL需要靠注释才能看懂,那这个URL设计就是失败的。

坑三:状态码返回200,错误信息写在body里

这个问题简直是灾难级别的存在。

// 错误示范:接口明明出错了,还返回200
HTTP/1.1 200 OK
{
  "code": -1,
  "message": "用户不存在",
  "data": null
}

200表示成功,这点毋庸置疑。如果你用了200但实际是错误,前端开发者的错误处理逻辑就会变成一坨屎。

正确的做法:

HTTP/1.1 404 Not Found
{
  "code": 40401,
  "message": "用户不存在"
}

或者:

HTTP/1.1 400 Bad Request
{
  "code": 40001,
  "message": "手机号格式不正确"
}

用正确的HTTP状态码,前端可以非常方便地做统一错误处理,不需要自己去解析你那套魔幻的code体系。

坑四:分页参数全靠约定

有些接口的分页参数是这样的:

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

然后另一个接口又是:

GET /api/orders?offset=0&size=10

同一个系统,两套分页约定。前端开发者每次对接新接口都要去翻文档确认参数名。

建议统一使用:

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

并且在响应中明确返回总数:

{
  "data": [...],
  "pagination": {
    "page": 1,
    "page_size": 20,
    "total": 156,
    "total_pages": 8
  }
}

这样前端可以统一封装一个分页组件,不用每次都重复写同样的逻辑。

坑五:版本号写URL里是耻辱

很多人喜欢这样:

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

不是说这种方式不行,而是它会带来很多维护上的麻烦。v1和v2并存的时候,你要同时维护两套代码。

更好的做法是:

  1. 接口设计初期尽量考虑周全,减少版本迭代
  2. 通过Header进行版本协商
  3. 如果必须URL版本,至少做好长期规划

坑六:过度设计,嵌套层级像俄罗斯套娃

有些程序员受HATEOAS毒害太深,写出来的接口返回数据结构是这样的:

{
  "id": 1,
  "name": "张三",
  "orders": [
    {
      "id": 101,
      "items": [
        {
          "product": {
            "id": 1001,
            "name": "iPhone",
            "price": 9999
          }
        }
      ]
    }
  ]
}

三层嵌套,看起来很「规范」,实际上前端拿到数据根本没法用。要么得写一堆空值判断,要么直接崩溃。

正确的做法是按需返回,或者提供fields参数让调用方指定要哪些字段:

GET /api/users/1?fields=id,name,email
GET /api/users/1?include=orders:limit(5)

最佳实践总结

说了这么多坑,总结一下我认为最重要的几个原则:

  1. 语义明确:HTTP方法、状态码、URL都要有明确的语义,不要让调用者猜
  2. 命名一致:同一套系统,命名风格要统一,参数格式要统一
  3. 文档先行:先写文档,再写代码。写文档的过程就是发现设计问题的过程
  4. 考虑调用方:接口是给前端用的,不是给自己炫技用的。多想想调用方的体验
  5. 错误处理要友好:错误信息要有价值,能让调用者快速定位问题

最后说两句

API设计这件事,说简单也简单,说复杂也复杂。简单在于,HTTP协议已经给你定义好了规则,你照着做就行。复杂在于,很多人连HTTP协议都没搞清楚就开始设计接口了。

下次当你准备新增一个接口的时候,先问自己三个问题:

  1. 这个接口的语义是什么?(查询、创建、更新、删除)
  2. 调用者能猜到这个接口是干什么的吗?
  3. 出错了,调用者能快速定位问题吗?

如果三个问题的答案都是肯定的,那这个接口设计大概率不会太差。

好了,吐槽完毕。如果觉得有用,欢迎转发。如果觉得我在胡说八道,那很正常,毕竟技术这东西,仁者见仁智者见智。

相关文章

追剧吐槽大会:我是如何从”就看一集”看到凌晨三点的
月薪5000,花呗欠8000:我是如何成为月光族天花板的
那些AI厂商不会告诉你的事:我花了三个月把主流AI工具测了个遍,发现了一些扎心的真相
🦞 手机依赖症:我和手机的双向奔赴,比谈恋爱还黏糊
忘带钥匙、忘关火、丢手机:我的人生就是一部丢三落四史诗
被一只”小龙虾”支配的日常:我和OpenClaw的爱恨情仇

发布评论