写了三年API,我还是想把键盘扔了

2026-07-22 8 0

干后端开发的,谁没被API折磨过?我见过太多项目,前端和后端互相指着对方骂,最后发现是API设计的问题。写三年了,今天来聊聊那些让人血压飙升的API设计,以及怎么避开这些坑。

REST不是你想怎么用就怎么用

很多人嘴上说RESTful,实际上就是CRUD+HTTP动词,然后觉得自己很规范。我见过有人把GET请求里放body,也见过有人用POST做一切事情,问就是"这样简单"。

拜托,REST是有灵魂的好吗?资源、表述、状态转移,这才是REST的三板斧。你一个查询接口,非要用POST,还洋洋得意说"我用POST更安全"——那不叫安全,那叫给后面维护的人挖坑。

// 别这样
POST /api/getUser

// 正常应该是这样
GET /api/users/123

错误处理:别让调用方猜谜

这个是我最想吐槽的。你有没有见过这种API:请求成功返回200,但是body里有个code字段是"error"?或者永远返回200,body里写"操作失败"?

调用方还得先看HTTP状态码,再看body里的code,再看message,这三层嵌套的逻辑让人头疼。我的建议是:HTTP状态码就用那几板斧——200成功,201创建,400客户端错误,401没认证,403没权限,404不存在,500服务器挂了。

body里统一返回这样的结构:

{
  "code": 0,
  "message": "操作成功",
  "data": {}
}

code=0是约定俗成的成功,其他都是错误。简单明了,不用猜。有些人非要搞一套自定义的状态码体系,结果文档写不清楚,调用方天天来问"这个code是什么意思"。

分页:要么不做,要么做好

列表接口不分页,数据量大了直接超时,服务器OOM,然后开始吐槽服务器配置太低。不分页的列表接口就是定时炸弹,不知道什么时候爆炸。

分页有两种常见方式:

第一种是offset+limit,适合数据量固定、很少有新增的场景:

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

第二种是cursor游标分页,适合实时数据、增量更新的场景:

GET /api/users?cursor=eyJpZCI6MTIzfQ\&page_size=20

返回的时候,务必带上总数和下一页游标:

{
  "code": 0,
  "data": {
    "list": [],
    "total": 1000,
    "next_cursor": "eyJpZCI6MTQzfQ"
  }
}

没有next_cursor就说明到底了,调用方只需要一个字段就能判断是否还有数据。

接口版本:升级的艺术

接口不可能永远不变,变的时候怎么办?直接改?前端没更新就炸了。怎么做版本控制?

路径版本是最直观的方式:

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

有些人喜欢用Header做版本,我觉得没必要。路径版本一眼就能看出调用的是哪个版本,文档也好写。除非你的接口是给App用的,App不能改URL,那再考虑Header方案。

升级的时候记住:新版本要能完全替代旧版本,不是加个字段就完事了。旧的v1要保证至少半年内还能用,给调用方足够的时间迁移。

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

我见过最离谱的API,是开发者得意洋洋地说"看我写的接口,名字都是英文的,很专业"。然后没有文档,接口名字还特别抽象,比如/api/query?type=user&status=1。前端问:status=1是什么意思?答曰:正常。

拜托,用户状态是正常还是异常,不写清楚谁知道你数据库里存的到底是1还是0还是2?

文档至少要包含:请求参数及含义、返回值结构、每个字段的类型和说明、错误码含义。有些团队用Swagger/OpenAPI,这很好,但文档要有人维护,接口变了文档就要变,不能文档和代码各走各的。

安全:别等被黑了才后悔

API安全是老生常谈了,但还是有人踩坑。最常见的是没做参数校验和没做权限校验。

参数校验不用多说,字符串长度、数字范围、枚举值,该校验就校验。有人觉得前端校验过了后端就不用校验——这话我只听到一半,后端校验是防御性的,前端校验是体验性的,谁也别替谁。

权限校验是重灾区。我见过查询接口没有校验当前用户是不是只能查自己的数据,结果A用户能看到B用户的数据。这不是bug,这是安全事故。

// 查询自己:正常
GET /api/users/me

// 查别人:权限校验
GET /api/users/123
// 如果123不是当前用户,返回403而不是静默返回空数据

写在最后

API设计看起来是技术活,实际上是沟通活。你的API是给调用方用的,怎么让对方用得舒服、用得明白、用得安全,这才是核心。

好的API设计有个特点:不用看文档也能猜出来怎么用。路径即语义,参数即意图,返回即预期。做到这一步,才算入门。

下次设计接口的时候,多想想:如果别人用我的API,心里会不会骂我?要是会,那就改。

相关文章

写了三年API,我还是想把键盘扔了
你的API到底有没有幂等性?这个问题能筛掉一半的CRUD工程师
N+1查询:那个让数据库哭爹喊娘、让老板以为你技术菜的元凶
RESTful API设计踩坑指南:我用惨烈教训换来的7条血泪经验
你以为代码写对了,API就快了?Too young,那些偷偷吃掉你200ms的幽灵
你那console.log调出来的bug,凭什么让我背锅?——日志规范实战

发布评论