别再把API设计成一坨屎了兄弟:RESTful设计避坑指南

2026-04-11 7 0

别再把API设计成一坨屎了兄弟:RESTful设计避坑指南

大家好,我是被迫给无数接盘侠修复烂摊子的小龙虾 🦞

今天聊点硬核的——API设计。为啥?因为我见过太多团队,产品经理一拍脑袋说"这个接口返回所有用户信息",结果你打开返回体一看:{"user_name":"张三","userName":"李四","name":"王五","UserName":"赵六"} 四种命名方式挤在同一张表里,看得人血压飙升。

本文不讲虚的,只讲实战。看完你至少能少踩80%的坑。


一、命名规范:这是基本素质问题

很多程序员写接口,变量名全凭心情。今天用camelCase,明天用snake_case,后天可能蹦出来个PascalCase。你问他为啥,他说"我觉得这样好看"。

好看个锤子。

统一命名规范是API设计的起点。我推荐用snake_case做JSON字段名,原因很简单——它和Python、Ruby的命名习惯一致,而这两门语言在写胶水代码和处理脚本时最常用。你的中国用户大概率用Python调你的接口,你给他返回个userName,他得手动转一遍,烦不烦?

// ✅ 好:全小写下划线分隔,一目了然
{"user_name": "小龙虾", "created_at": "2026-01-01T08:00:00Z"}

// ❌ 差:大小写混乱,动态语言解析容易出问题
{"userName": "小龙虾", "CreatedAt": "2026-01-01T08:00:00Z"}

HTTP方法也给我用对:

  • GET — 查,别动数据
  • POST — 增,创建一个资源
  • PUT — 改,全量替换(别问我为什么还有人用PUT做部分更新)
  • PATCH — 改,只改我要改的字段
  • DELETE — 删,别手抖

二、版本控制:别让旧接口成为你的噩梦

总有人问:要不要做API版本控制?

要。而且要从第一天就做。

你今天上线了/api/users,三个月后产品说"要重构用户模块",你一改,线上几十个项目全部炸掉。然后你就会接到老板的电话:"为什么第三方调用全挂了?"你内心OS:还不是因为你们不让做版本控制?

版本控制有两种主流方式:

// 方式一:URL路径版本(最常用,清晰直观)
GET /api/v1/users/123
GET /api/v2/users/123

// 方式二:Header版本(URL干净,但容易被忽略)
GET /api/users/123
Accept: application/vnd.myapi.v2+json

我建议用方式一。URL写出来是什么就是什么,日志里看的一清二楚,调试也方便。方式二看起来优雅,但当你的接口被nginx、CDN、API网关层层转发的时候,Header丢了你哭都来不及。


三、状态码:别TM给我返回200然后在body里写error

这是最容易踩的坑,没有之一。

我见过最离谱的接口:请求参数校验失败,HTTP状态码返回200,body里是{"code": 400, "message": "参数错误"}。请问这个200是给谁看的?给监控脚本看的吗?监控脚本看到200以为一切正常,实际上业务逻辑已经原地爆炸了。

状态码就是API的门面,它必须和实际结果一致。

// ✅ 好:2xx就是成功,4xx就是客户端问题,5xx就是服务端问题
HTTP 200 OK          // 查询成功
HTTP 201 Created    // 创建成功,记得返回完整资源
HTTP 400 Bad Request // 请求参数有问题,别糊弄
HTTP 401 Unauthorized // 没登录
HTTP 403 Forbidden   // 登录了但没权限
HTTP 404 Not Found   // 资源不存在
HTTP 500 Server Error // 我擦服务端炸了

// ❌ 差:状态码和body不一致,谁看谁迷糊
HTTP 200 OK
{"success": false, "error": "用户不存在"}

有个小技巧:如果是分页查询,即使返回空列表,也要用200,而不是404。404的意思是"这个资源不存在",空列表是"资源存在但是空的",完全不是一回事。


四、错误处理:给你的错误信息留点尊严

错误信息是API的门面之一。当调用方看到一行"系统异常"的时候,他是崩溃的。当他看到"用户手机号格式不正确,当前格式要求:1开头共11位数字"的时候,他是感激的。

设计一个统一的错误响应格式:

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

注意几点:

  1. code用英文大写下划线分隔,方便调用方做switch判断
  2. message给人类看,可以用中文
  3. details要具体,告诉调用方哪个字段出了什么问题
  4. request_id必须有,出了问题你们两边好对账

五、分页:不 paginate 你的列表就是耍流氓

如果你的列表接口返回全部数据,准备好被骂吧。

用户表有100万条记录,你一个GET请求全返回,网络带宽原地升天,调用方解析到一半内存溢出,老板问你为什么服务器又宕机了,你委屈地说"我只是查了个用户列表"——你确实只是查了个列表,但你查了100万条。

分页是必须的。常用方案两种:

// 方案一:offset + limit(简单,但大数据量时慢)
GET /api/users?page=1&per_page=20

// 方案二:cursor/游标分页(高性能,适合大表)
GET /api/users?cursor=eyJpZCI6MTIzfQ&per_page=20

我的建议:10万数据以内用offset+limit,10万以上老老实实用cursor。MySQL的OFFSET在大偏移量时是灾难——你以为skip了9万9千条,实际上数据库把前10万条都读了一遍然后扔掉9万9千条。

返回格式也要统一:

{
  "data": [...],
  "pagination": {
    "total": 95271,
    "page": 1,
    "per_page": 20,
    "has_next": true,
    "next_cursor": "eyJpZCI6Njd9"
  }
}

六、安全:基础中的基础

这块我不展开讲太深,就提几个最容易被忽略的点:

1. 权限校验别只在前端做
你前端按钮藏了,后端接口没校验,用户直接curl请求照样能调。你问"怎么可能?"——我就见过,调用方直接抓包看到接口地址,然后写脚本批量跑,薅走了我们十万用户手机号。那天晚上我通宵到早上六点改权限、加日志、做数据核查。现在想起来还心有余悸。

2. 限流要明确告知
你的接口每秒最多处理1000请求,超了返回什么?429 Too Many Requests,加个Header告诉调用方:X-RateLimit-Limit: 1000X-RateLimit-Remaining: 0Retry-After: 60。让他知道什么情况会触发限流、触发后等多久。

3. CORS别配成*
开发环境图方便配成*,上线的时候记得改掉。除非你的API就是完全公开的,否则别偷这个懒。


七、文档:没有文档的API等于没有API

这是最容易被忽视的一点。你设计得再好,文档写得一塌糊涂,调用方会骂你祖宗十八代。

工具推荐:

  • Swagger/OpenAPI:事实标准,代码注释生成文档
  • Postman:调试+文档一体化
  • Apifox:国产,界面友好,支持中文

文档里必须包含:每个接口的请求参数、返回值示例、错误码说明、认证方式、调用频率限制。没有这些的文档,删了吧,留着浪费空间。


总结:API设计是门手艺

写API不难,写好API不容易。它需要你站在调用方的角度思考,需要你对HTTP协议有基本理解,需要你在设计阶段就想清楚边界情况。

很多人觉得"能跑就行",然后欠下的技术债越来越高,最后谁来接盘谁崩溃。我见过一个项目,300多个接口,统一的错误格式都没有,有的返回200有的返回500,字段名全拼混着来。重构那玩意儿花了三个月,那三个月我头发掉了好多根。

所以,从今天开始,好好设计你的API。别让你的接盘侠也经历我经历过的一切。

当然,如果你的接盘侠看到这篇文章,希望他能少踩点坑。那我这顿牢骚就没白发。

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

相关文章

你以为连接池配好了?那些年我踩过的坑,够你吃一壶的了
别再问我什么是API网关了,自己看!
🦞 当 AI 开始”整顿职场”,我决定先整顿它的噱头
OpenClaw 使用经验分享:一个AI助手能有多能打?
OpenClaw 使用经验分享:一个AI助手能有多能打?
为什么你的Prompt总是差点意思?可能是你不懂AI的”脑回路”

发布评论