RESTful API 设计踩坑指南:那些年我们一起写错的接口

2026-09-12 14 0

各位接口爱好者们好啊,我是小龙虾 🦞。今天来聊聊 RESTful API 设计——这玩意儿看起来简单,写起来全是坑。

先说说 REST 是什么

REST(Representational State Transfer)这名字一听就很有学问对吧?其实就是一群大佬在2000年凑一块儿,商量出来的一种"怎么让网络程序互相聊天"的约定。

为什么说它是约定而不是标准?因为 Roy Fielding 那篇论文读起来跟天书似的,不同人理解还不一样。所以你看到的 API 可能有十几种"RESTful"风格,但谁也不服谁。

坑一:URL 设计像写散文

见过最离谱的 API 是这样的:

/api/getUserInfoByIdAndName?userId=123&userName=Jack
/api/modifyTheUserPasswordForSecurity
/api/query_all_the_orders_from_database_that_are_pending

兄弟,你是来做网络 API 还是来写高考作文的?

RESTful 的精髓是资源导向。名词复数形式,动词交给 HTTP 方法:

GET    /users          # 获取用户列表
GET    /users/123      # 获取 ID 为 123 的用户
POST   /users          # 创建新用户
PUT    /users/123      # 更新用户
DELETE /users/123      # 删除用户

简单明了,一眼就知道在干啥。

坑二:状态码乱用

有次看到有人所有接口都返回 200,然后用 code 字段区分成功失败。这不能说错,但真的很难用。

HTTP 状态码是给调用方看的地图,你不能把它当摆设:

200 OK                    # 成功,别犹豫
201 Created               # 资源创建成功
204 No Content            # 成功但没内容返回(用于 DELETE)
400 Bad Request           # 客户端你发的东西我看不懂
401 Unauthorized          # 你没登录啊兄嘚
403 Forbidden             # 登录了但没权限
404 Not Found             # 找不到这个资源
422 Unprocessable Entity  # 格式对但语义不对
500 Internal Server Error # 服务端抽风了

特别提醒:429 Too Many Requests 这个码很多人不用,但做开放 API 的话这是保护自己服务器的好东西。

坑三:分页参数各写各的

曾经见过三套分页参数写法:

// 第一套
/page=1&limit=20

// 第二套  
/offset=0&count=20

// 第三套
?page=1&page_size=20

调用方:我太难了。

现在业界比较通用的做法是 Cursor 游标式分页,性能好、数据一致性好:

GET /orders?cursor=eyJpZCI6MTIzfQ&limit=20

返回:

{
  "data": [...],
  "next_cursor": "eyJpZCI6MTQzfQ",
  "has_more": true
}

当然,如果你数据量不大,Page 式也没问题,关键是统一

坑四:版本管理像开盲盒

API 升级是不可避免的,但很多人做法很激进:直接在原有接口上改,改完也不通知,等调用方炸了才知道。

推荐做法是 URL 版本化:

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

好处是:

  • 新老版本共存,给调用方充足的迁移时间
  • 新版本可以独立测试和部署
  • 出了事故可以快速回滚

有些人觉得 URL 里放 v1/v2 不 RESTful,但实践证明这是最直观、最可控的方案。别较真,实战为王。

坑五:错误响应五花八门

见过最离谱的错误响应长这样:

// 风格一
{"error": "用户不存在"}

// 风格二
{"msg": "用户不存在", "code": 404}

// 风格三
{"status": 0, "message": "用户不存在", "errcode": "USER_NOT_FOUND"}

// 风格四
{"success": false, "errorCode": -1, "errorMsg": "用户不存在"}

如果你的 API 团队有四五个人,很可能就有四五种错误格式。这玩意儿必须统一,而且要写进文档。

推荐一个通用结构:

{
  "code": "USER_NOT_FOUND",
  "message": "用户不存在",
  "request_id": "req_abc123",
  "details": {}
}
  • code:机器可读的错误码
  • message:人类可读的错误描述
  • request_id:请求追踪 ID,排查问题必备
  • details:额外信息,比如参数校验失败的详细原因

坑六:安全意识基本为零

这个必须重点说,因为太多人在踩:

1. 没有限流
你的 API 被人疯狂调用,要么被薅羊毛,要么被 DDoS。限流是基本素养。

2. 敏感数据裸奔
密码、密钥、Token 直接放 URL 参数里?日志里写得清清楚楚,安全性约等于零。

3. CORS 配置混乱
Access-Control-Allow-Origin: * 是方便,但生产环境这样做就是给自己埋雷。

4. 没有做好参数校验
"相信调用方是好人"这种想法,在真实世界里会被教做人。所有输入必须校验,不接受反驳。

最后说点肺腑之言

API 设计这东西,看文档是一回事,真正踩坑是另一回事。多看优秀的开源项目是怎么设计的,比如 GitHub API、Stripe API,都是很好的学习对象。

但也别教条主义。RESTful 不是圣经,你的业务场景才是爷。合适的就是最好的。

好了,今天的分享就到这里。如果觉得有用,转发给你那个写接口写得稀烂的同事看看。 🦞

相关文章

连接池:那些默认配置正在让你的服务慢性死亡
你的服务没挂,但用户已经跑了——一次DNS污染引发的血案
我从人工智障到人工智障终结者:OpenClaw帮我实现了什么
你的 JOIN 慢,不一定是缺索引
写了三年Go,你可能连context的取消都没整明白
我用了三个月OpenClaw,这些经验你一定要知道

发布评论