RESTful API 设计:我踩过的坑,比你走过的桥还多

2026-07-01 13 0

做后端开发这些年,我见过太多「看起来很美」的 API,写出来却让人想骂街。有的返回 200 实际是错误,有的命名全靠猜,有的文档写得天花乱坠一跑起来全是 bug。今天不整虚的,咱就聊聊 RESTful API 设计里那些容易被忽略但巨坑的细节。

1. 状态码:你真的会用吗?

最离谱的见过什么?返回 200 状态码,body 里写着 {"code": 500, "message": "服务器内部错误"}。我当时就???这不纯属糊弄人吗?

HTTP 状态码是给人看的,不是给你偷懒用的。正确姿势:

  • 200 - 一切正常,返回你期望的数据
  • 201 - 创建成功(POST 返回这个,比 200 讲究)
  • 400 - 你的请求有问题,比如参数校验失败
  • 401 - 没认证,先登录去
  • 403 - 认证了但没权限,别挣扎
  • 404 - 资源不存在,不是「用户不存在」就是「订单不存在」
  • 500 - 我们的锅,但这种错误一般不要让用户看到详情

有个原则:能用状态码表达的意思,别放到 body 里。你要是连状态码都懒得设对,那你写的 API 迟早被人吐槽到自闭。

2. 命名:拼音 vs 英文?都不对!

见过用拼音命名的 API 吗?/api/getUserInfoById 这种?每次调用都觉得自己在用老年机。拼音命名是上世纪的遗产,英文才是正道。

但纯英文也不一定对。很多人喜欢走极端:

// 过度设计型
GET /api/v1/users/{user_id}/account-settings/preferences/notifications/sms

// 随意型
GET /api/getUser
POST /api/setUser

// 正常型
GET /api/users/{id}
PATCH /api/users/{id}

RESTful 的精髓是「名词优先」,动词用 HTTP 方法表达。别搞什么 getUserdeleteUserupdateUser 一股脑全堆在 URL 里。资源是复数形式,路径结构要扁平。

有个小技巧:你的 URL 应该能猜出来。新来的同事看了你的 API 文档,能猜到某个功能的接口大概长什么样,这就是好的设计。

3. 分页:最容易翻车的地方

「这个接口怎么返回这么多数据?」——十有八九是分页没做好。分页是个看起来简单实际上巨坑的功能。

常见的分页方式:

// 偏移分页(最常见,但有性能问题)
GET /api/users?page=1&page_size=20

// 游标分页(适合大数据量,性能稳定)
GET /api/users?cursor=eyJpZCI6MTAwfQ&limit=20

// 区间分页(适合需要快速跳转的场景)
GET /api/users?offset=0&limit=20

偏移分页的坑:当你有 100 万条数据,查询第 99 万条起的前 20 条,数据库要扫描前面 99 万条才能给你返回。这种场景下,游标分页才是正确答案。

分页返回格式也要规范:

{
  "data": [...],
  "pagination": {
    "total": 1000000,
    "page": 1,
    "page_size": 20,
    "has_next": true
  }
}

别返回这种:[1, 2, 3, 4, 5, ...] 然后让我猜有多少条。

4. 错误处理:让人能看懂的那种

错误处理是 API 的脸面。很多接口返回的错误让人摸不着头脑:

// 这种错误消息等于没说
{
  "error": "Invalid parameter"
}

// 这种才叫有诚意
{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "请求参数校验失败",
    "details": [
      {"field": "email", "message": "邮箱格式不正确"},
      {"field": "age", "message": "年龄必须大于0"}
    ]
  }
}

错误码比错误消息更重要。消息给人看,错误码给程序看。你要是每次错误都只返回一个「操作失败」,调用方根本没法自动化处理。

还有一点:错误消息不要暴露内部细节。你要是把 SQL 错误、堆栈信息直接返回出去,不是给人学习的机会,是给黑客敞开大门。

5. 版本控制:早做早超生

「接口要兼容旧版本吗?」「不加版本号行不行?」——每次有人问这种问题,我就知道他们迟早要踩这个坑。

版本控制的三种主流方式:

// URL 路径版本(最直观,GitHub 在用)
GET /api/v1/users
GET /api/v2/users

// Header 版本(Clean URL,但容易被忽略)
GET /api/users
Accept: application/vnd.api+json; version=2

// Query 参数版本(简单但不推荐)
GET /api/users?version=2

我的建议:用 URL 路径版本。简单粗暴,调试方便,一眼就能看出调用的是哪个版本。别觉得丑,好用才是硬道理。

版本迭代的时候,不要删除旧版本,至少保留 6-12 个月。给调用方足够的时间迁移。你要是上午发版下午就下线旧版,等待你的是连环夺命 call。

6. 安全性:别等被刷了再后悔

API 安全是个老生常谈但总被忽视的话题。几个必须要注意的点:

  • 限流(Rate Limiting):没限流的 API 就是裸奔。一个接口一天被调几十万次,服务器说挂就挂。
  • 参数校验:后端必须校验所有输入,别相信前端传的任何一个参数。
  • 敏感数据:密码、token 这种东西,绝对不能出现在 URL 参数里(会被日志出卖)。
  • CORS:跨域配置要严谨,别 * 一把梭。

总结

好的 API 设计不是什么高深莫测的东西,核心就一句话:让人用着舒服、出错了能快速定位、安全性不掉链子。

你写的 API 就是你的名片。下次接手别人写的 API,你希望看到什么样的?是结构清晰、错误明确、文档齐全?还是满屏 map<String,Object>、状态码永远 200、错误消息永远「系统繁忙」?

己所不欲,勿施于人。共勉。

相关文章

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

发布评论