为什么你的API总是被人骂?一位老油条的掏心窝子经验

2026-04-15 6 0

为什么你的API总是被人骂?一位老油条的掏心窝子经验

干后端这么多年,我见过太多"能用但不好用"的API。有的返回结构像开盲盒,有的错误信息写着"操作失败请联系管理员",还有的接口名字叫getDataByType2——我也不知道Type1去哪了。

今天不整虚的,就聊聊那些真正让API变好用的东西。有些是我踩过的坑,有些是看到别人踩坑后的反思。看完了要是觉得没用,你来骂我。

一、URL设计:别把API写成迷宫

很多人的API URL是这样的:

GET /api/v1/getUserInfoById?id=123
POST /api/v1/user/query
GET /api/v1/getData

看到这种URL,我血压都高了。URL应该是名词,不是动词。动作交给HTTP方法。

正确姿势:

GET    /api/v1/users/123        # 获取用户
PATCH  /api/v1/users/123        # 部分更新用户
DELETE /api/v1/users/123        # 删除用户
GET    /api/v1/users/123/orders # 获取用户的订单

RESTful不是银弹,但你至少把"获取"和"操作"分清楚。

二、状态码:用对了是专业,用错了是灾难

的状态码管理简直是一言难尽。常见问题:

  • 所有成功都返回200,所有失败都返回400
  • 明明是服务器挂了,返回个200加个{"success": false}
  • 错误信息就三个字:"出错了"

我的建议是,状态码要用准:

200 OK              # 成功,且有返回
201 Created         # 创建成功,Response Header带Location
204 No Content      # 成功,但没返回体(常见于DELETE)
400 Bad Request     # 参数校验失败
401 Unauthorized    # 没登录
403 Forbidden       # 登录了但没权限
404 Not Found       # 资源不存在
422 Unprocessable   # 格式对但语义错
429 Too Many        # 请求过于频繁
500 Internal Error  # 服务器挂了

最关键的一点:错误响应必须包含足够的信息让客户端知道发生了什么

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

这种响应,客户端开发者看到会感谢你的。

三、版本管理:不做版本管理的API都是在给自己挖坑

迟早你会遇到要破坏性改动的情况。怎么办?硬着头皮改?然后线上开始报成堆的bug?

版本管理是必经之路。主流方案:

# URL版本号(GitHub、Stripe在用,简单直接)
GET /api/v1/users
GET /api/v2/users

# Header版本号(更"优雅"但不够直观)
GET /api/users
Accept: application/vnd.api+json; version=2

我的建议是URL版本号。为什么?

  1. 调试方便,直接改URL就能测新版本
  2. 日志里一目了然
  3. CDN和网关配置简单

版本什么时候升?当你需要破坏性变更的时候。增删字段不算,字段改名要算。

四、分页:无分页的API都是定时炸弹

你的用户表有一亿条数据,前端请求GET /api/users,你打算返回全部?

轻则超时,重则OOM。

分页是必须的。两种常见方式:

# Offset分页(简单但有性能问题)
GET /api/users?page=1&per_page=20

# Cursor分页(性能好但不能跳页)
GET /api/users?cursor=abc123&per_page=20

大数据量+高频请求,用Cursor分页。普通后台管理界面,Offset够用。

返回结构要统一:

{
  "data": [...],
  "pagination": {
    "total": 1000000,
    "per_page": 20,
    "current_page": 1,
    "total_pages": 50000,
    "has_next": true,
    "has_prev": false
  }
}

五、幂等性:这个概念救过我的命

什么叫幂等?就是执行一次和执行N次,效果一样。

为什么要考虑这个?因为网络会超时、客户端会重试、用户会手抖点两下。

这些操作必须幂等

  • GET - 天然幂等,读一百遍还是那个结果
  • DELETE - 删两次和删一次,都是删了
  • PUT - 完整替换,幂等

这些操作不幂等(要特别处理):

  • POST - 创建资源,重复提交会创建多个
  • PATCH - 部分更新,取决于语义

不幂等的操作怎么办?用幂等Key

POST /api/orders
Idempotency-Key: client-generated-uuid-12345

服务端根据这个Key做去重,重复请求直接返回上次的结果。支付场景必用。

六、文档:没文档的API等于没API

这句话我说一百遍都不嫌多。

你的API再优雅,没人知道怎么用就是白搭。文档要包括:

  • 每个端点的完整说明(不只是"获取用户"这种废话)
  • 请求参数的类型、约束、含义
  • 响应结构的每个字段说明
  • 错误码列表和触发条件
  • 认证方式
  • 实际调用示例

工具的话,OpenAPI(Swagger)规范是行业标准。配合Swagger UI或Redoc,既是文档又是调试工具。

文档写完了,发给调用方之前,自己先按照文档把每个接口调用一遍。你会发现文档里各种没说清楚的地方。

七、最后说几句

API设计没有完美答案,只有trade-off。但有些原则是普适的:

  1. 一致性:内部风格要统一,别这个接口用驼峰那个用下划线
  2. 可预测:按照文档来用,应该能正常工作
  3. 容错性:客户端可能犯错,API要有足够的校验和友好的错误提示
  4. 演进能力:一开始就考虑扩展性,别到时候改不动

好的API用起来的感觉就是"理所当然",坏的API用起来就是"这个设计是认真的吗"。

代码写出来是给别人用的,API更是。

以上,共勉。


有问题欢迎留言交流。当然,如果你说你的API被骂了,先别急着甩锅给调用方,看看是不是自己设计确实有问题。

相关文章

你的HTTP客户端正在悄悄偷走你的性能:那些连接池不会告诉你的事
OpenClaw 使用经验分享:一只小龙虾的AI调教记录
当别人还在纠结服务器配置,我已经在用AI工具搞钱了
为什么你的API总是被人吐槽?一次把REST设计说清楚
数据库事务:我赌你不知道这几个怪事
REST API 设计师:我劝你善良,别什么都返回 200

发布评论