为什么你的API总被吐槽?血泪教训总结的RESTful设计避坑指南
做后端开发这么多年,我见过太多「能跑就行」的API,也见过太多因为API设计烂而被喷得体无完肤的项目。更见过产品经理拿着接口文档一脸懵逼,开发自己过两天再看自己写的代码也懵的情况。
今天不整虚的,直接上硬菜——我从无数次踩坑中总结出来的RESTful API设计避坑指南。全文干货,建议先收藏再看。
一、先搞清楚什么是真正的REST
很多人在简历上写「精通RESTful API设计」,结果一问他HTTP方法有哪些,都只能说个GET和POST。兄弟,你这不叫精通,这叫「听说过」。
REST架构风格的核心就六条原则:客户端-服务器、无状态、缓存、统一接口、分层系统、按需代码。其中最容易被忽略的就是「统一接口」——你的API应该长什么样,其实是有规范的。
资源(Resource)是核心,所有东西都是资源。URI是资源的地址,HTTP方法是操作资源的方式。
举个经典错误:
// 错误示范
POST /api/getUser
POST /api/deleteUser
POST /api/updateUser
// 正确姿势
GET /api/users/{id}
DELETE /api/users/{id}
PATCH /api/users/{id}
看出来了吗?同一个资源,不同操作,用不同的HTTP方法,URI保持一致。这就是REST的精髓。
二、URI设计:别把API写成作文
见过最离谱的API是这个:
/api/v1/queryUserInfoByIdAndReturnJsonFormat
/api/v1/getAllTheUsersWhoHaveOrdersInTheLast30Days
我怀疑写这个API的兄弟是故意的,就是为了让自己不可替代。
URI设计记住这几个原则:
1. 用名词,不用动词
资源是名词,操作是HTTP方法。下面这个表格记好了:
| 操作 | HTTP方法 | 示例 |
|---|---|---|
| 获取资源 | GET | GET /users |
| 获取单个资源 | GET | GET /users/123 |
| 创建资源 | POST | POST /users |
| 更新资源 | PUT/PATCH | PUT /users/123 |
| 删除资源 | DELETE | DELETE /users/123 |
2. 层级结构要合理
// 用户123的订单
GET /users/123/orders
// 订单456的商品
GET /orders/456/items
层级关系要符合业务逻辑,不要嵌套太深。建议最多三层,再深就考虑用查询参数。
3. 查询参数用来过滤,别用来做操作
// 正确:筛选是查询参数
GET /users?status=active&role=admin
// 错误:把操作放到了查询参数里
GET /api/getUsersByStatus?status=active
三、状态码:别总是200 OK
有些同学的API,返回永远都是200,哪怕是删除了不存在的数据也200。这是掩耳盗铃。
HTTP状态码是API的语言,要用它正确表达含义:
2xx 成功系列
- 200 OK:请求成功,返回内容
- 201 Created:资源创建成功,响应头带Location
- 204 No Content:成功但无返回内容(常见于DELETE)
4xx 客户端错误系列
- 400 Bad Request:请求参数有问题
- 401 Unauthorized:未认证(没登录)
- 403 Forbidden:已认证但没权限
- 404 Not Found:资源不存在
- 409 Conflict:资源冲突(如重复创建)
- 422 Unprocessable Entity:请求格式对但语义错
5xx 服务端错误系列
这个简单,出了5xx就是后端背锅。别解释,直接查日志修bug。
一个血泪教训:千万别为了省事,所有错误都返回400加一个「系统繁忙」的消息。客户端需要知道具体哪里错了,才能正确处理。
四、请求体与响应体:格式化是基本礼仪
JSON已经是最通用的格式了,别再搞什么XML、Custom YAML。除非你有特殊理由。
请求体规范
{
"username": "zhangsan",
"email": "zhangsan@example.com",
"age": 28
}
字段命名统一用camelCase或snake_case,全项目保持一致。切忌一会儿驼峰一会儿下划线。
响应体规范
统一响应结构,这是最重要的规范之一:
{
"code": 0,
"message": "success",
"data": {
"id": 123,
"username": "zhangsan"
}
}
或者:
{
"success": true,
"data": {},
"error": null
}
选一种,全项目统一。别一个模块用code,一个模块用success,调用方会疯的。
分页响应
{
"data": [],
"pagination": {
"page": 1,
"pageSize": 20,
"total": 100,
"totalPages": 5
}
}
分页参数用page+pageSize或者offset+limit,选一种。但一定要返回总数,这是前端分页组件的基本需求。
五、版本管理:给自己留条活路
接口一旦发布,就是合约。改它代价很大。所以从一开始就规划好版本策略。
/api/v1/users
/api/v2/users
版本号放在URL路径里,不要放Header里。放在Header里是给自己找麻烦,前端同学会骂你。
什么时候升版本?
- 删除或重命名字段
- 改变字段类型
- 改变字段含义
- 移除或废弃端点
什么时候不改版本?
- 新增字段(向后兼容)
- 新增API端点
- 性能优化
六、安全:这事儿不能省
认证与授权
认证和授权是两码事:
- 认证(Authentication):你是谁?
- 授权(Authorization):你能干什么?
API认证用JWT或者OAuth2,别再明文传输密码或者把token放URL里。
// 正确:token放Header
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
// 错误:token放URL(会被浏览器历史记录、日志等记录)
GET /api/users?token=eyJhbGciOiJIUzI1NiIs...
参数校验
永远不要相信客户端传来的数据。每一个参数都要校验:
// 参数校验伪代码
if (!id || typeof id !== number || id <= 0) {
return res.status(400).json({
code: 400,
message: id参数无效
});
}
限流
你的API对外开放,就要做限流。不然被人一个for循环请求打挂,别怪我没提醒你。
// 响应头带限流信息
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640000000
七、文档:这活儿值十万
我见过太多「代码即文档」的项目,注释都没几行,更别说接口文档了。
接口文档要包含:
- 端点描述
- 请求参数(类型、是否必填、取值范围)
- 响应结构(每个字段的含义)
- 错误码说明
- 请求示例
- 响应示例
工具推荐:Swagger/OpenAPI、Apifox、Postman。选一个用起来,团队协作效率能提升一倍。
最烂的文档是「接口文档请看代码」。说这话的人,我怀疑他自己是唯一能看懂代码的人。
总结
API设计是后端开发的基本功,设计得好,调用方爽,自己后续维护也爽。设计得烂,那就是给自己埋雷,指不定哪天就炸。
记住这几个核心要点:
- 资源导向,名词复数形式
- 正确使用HTTP方法
- 合理使用状态码
- 统一响应结构
- 做好版本规划
- 安全措施不能省
- 文档要写,而且要写好
代码写得好是基本功,API设计得好是加分项。从今天开始,重新审视一下你手上的接口,有坑的赶紧填,别等到被人指着鼻子骂再来改。
有问题欢迎留言,我看到了会回。