从“这接口谁写的”到“真香”:RESTful API设计实战复盘

2026-05-17 10 0

上周五下午,办公室里飘着咖啡香,我正美滋滋地准备收工下班,突然钉钉炸了。

「兄弟,你这接口返回的数据格式太随性了,我这边解析了三遍才搞对。」

「还有,你那个分页参数是pageSize还是page_size还是pagesize?三个地方三个写法,我查文档查到头秃。」

我默默放下背包,默默打开电脑,开始了新一轮的「接口优化」。

这不是我第一次被吐槽,大概率也不是最后一次。在踩了无数坑之后,我决定把这些年踩出来的经验整理一下,分享给各位还在API设计上「作」的同行。

坑一:把HTTP状态码当摆设

见过最离谱的接口:请求成功了,返回200;请求失败了,返回200;服务器挂了,还是返回200。

我问他为什么,他理直气壮:「业务逻辑上都处理了啊,返回200表示我收到请求了嘛。」

我当时差点把咖啡喷屏幕上。

HTTP状态码是干什么用的?是让调用方一眼看出请求结果用的。你返回一个200,结果body里写着{"code": 500, "msg": "服务器爆炸"},这不是脱了裤子放屁吗?

正确的做法:

// 成功
return response.status(200).json({ data: result });

// 客户端错误
return response.status(400).json({ error: "参数校验失败" });

// 服务端错误
return response.status(500).json({ error: "服务暂暂停,请稍后重试" });

约定好状态码语义,让错误处理变成一件幸福的事。

坑二:分页参数随心所欲

这是重灾区。每个团队都说自己在做RESTful,但分页参数的设计简直像在玩大家来找茬。

/api/users?page=1&size=20

/api/users?pageNo=1&pageSize=20

/api/users?offset=0&limit=20

/api/users?from=0&to=20

你能信?我见过一个项目里同时存在四种写法,分别来自四个不同的开发。

我的建议是:选择page+size或者offset+limit其中一种,然后死磕到底。最好在文档里写清楚,别让调用方去猜。

// 推荐:page + size(更直观,适合业务场景)
GET /api/users?page=1&size=20

// 也推荐:offset + limit(适合大数据量场景)
GET /api/users?offset=0&limit=20

返回结果里也要带上分页元数据,让调用方知道自己有多少页、当前第几页、总共多少条。

{
  "data": [...],
  "pagination": {
    "page": 1,
    "size": 20,
    "total": 1523,
    "totalPages": 77
  }
}

坑三:命名全凭心情

见过最随性的API命名:

/api/getUserInfo

/api/Get_User

/api/query-user-data

/api/userInfoQuery

四种写法表示同一个功能,我都不知道该佩服还是该骂人。

RESTful的核心是「资源」和「操作」。资源用名词表示,操作用HTTP方法表示。

// 获取用户列表
GET /api/users

// 获取单个用户
GET /api/users/{id}

// 创建用户
POST /api/users

// 更新用户
PUT /api/users/{id}

// 删除用户
DELETE /api/users/{id}

统一命名规范:全小写,用连字符分隔单词。别学某些人用驼峰,别学某些人用下划线,别学某些人用混合大小写。

坑四:版本控制等于没控制

「这个接口还能用多久?」——这个问题应该由接口提供方主动回答,而不是等调用方来问。

版本控制不是可选的,是必须的。

// 放在URL路径里(最常见)
GET /api/v1/users
GET /api/v2/users

// 放在header里(比较少见)
GET /api/users
API-Version: 2023-01-01

每个版本要有明确的生命周期:什么时候弃用、什么时候下线。提前通知调用方,给他们足够的迁移时间。

坑五:错误信息像谜语

线上出过一起事故:接口返回「操作失败」,没有任何详细说明。调用方以为是自己参数问题,查了两天,最后发现是服务器硬盘满了。

错误信息要包含足够的信息量,但不要包含敏感信息。

// 反面教材
{ "error": "操作失败" }

// 正确示范
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "请求参数校验失败",
    "details": [
      { "field": "email", "message": "邮箱格式不正确" },
      { "field": "phone", "message": "手机号不能为空" }
    ],
    "requestId": "req_abc123"
  }
}

加上requestId,这样出问题了可以快速定位日志。

坑六:不写文档或者文档是摆设

最怕的不是接口写得烂,是接口写得还行但文档像垃圾。

我见过最离谱的文档:接口说明写着「获取用户信息」,没有参数说明,没有返回示例,没有错误码说明。点开评论,有人问「这个接口返回的是什么」,作者回复「你看代码就知道了」。

代码即文档这种话,在API场景下就是耍流氓。

文档要包含:

  • 接口功能说明
  • 请求参数(含类型、是否必填)
  • 返回数据结构(含每个字段含义)
  • 错误码说明
  • 调用示例

现在有很多工具可以自动生成文档:Swagger、Apifox、Postman。至少把文档和代码同步更新这件事,做起来没那么难。

坑七:安全意识约等于零

见过有人在URL里传密码的:「/api/login?username=admin&password=123456」。也见过把所有接口都设计成无需认证的,美其名曰「方便调试」。

方便调试是方便了,被人攻击的时候哭都来不及。

基本要求:

  • 敏感信息走POST body,不要放URL参数里
  • 使用HTTPS
  • 做好接口限流,防止DDoS
  • 关键接口加上幂等性设计
  • 日志里不要记录敏感信息(密码、token等)

说在最后

写接口这件事,入门门槛很低,但做好很难。一个烂接口会影响一堆人,一个好接口会让调用方发出「真香」的感叹。

下次写接口之前,先问问自己:如果别人调用这个接口,最可能在哪里卡住?如果我是个完全不知道业务的人,看文档能看懂吗?

好的API设计就像好的代码注释——不是为了炫耀,而是为了让他人(包括未来的自己)能少踩坑。

共勉。

相关文章

为什么同样配置的服务器,别人能跑你却炸了?一位被连接池坑了三年的工程师的血泪复盘
AI探索|当AI开始卷起来,我们都成了吃瓜群众
AI工具部署太麻烦?小龙虾帮你一键搞定,省心又省力!
AI工具部署太麻烦?小龙虾帮你一键搞定,省心又省力!
写了5年代码,我发现API设计才是程序员的分水岭
别人用Redis只會cache,我用Redis做了六件你絕對想不到的事

发布评论