原创

第一个接口怎么设计

paste-image-1784084155013.png

很多人第一次写接口时,会把重点放在“能不能返回数据”。只要前端能调通,页面能显示,就觉得接口设计完成了。

但接口不是临时函数。它是前端、后端、数据库、权限、错误处理和未来扩展之间的契约。一开始设计得太随意,后面每次改功能都会变成连锁反应。

第一个接口不需要复杂,但一定要清楚、稳定、可理解。

先明确接口服务什么动作

写接口前,不要先想 URL,而要先想用户动作。

用户是在创建项目、获取列表、更新设置、上传文件、提交订单,还是查看结果?接口应该服务一个明确动作,不要把多个不相关的动作塞进同一个接口。

比如“创建项目”和“修改项目设置”应该是两个接口;“获取项目列表”和“获取项目详情”也应该分开。

接口越清楚,前端越容易使用,后端越容易维护,问题也越容易排查。

用资源而不是动词组织路径

常见的新手写法是:

/api/createProject
/api/getProjectList
/api/updateProject
/api/deleteProject

这种写法能用,但长期会变乱。更推荐用资源路径加 HTTP 方法表达动作:

GET    /api/projects
POST   /api/projects
GET    /api/projects/:id
PATCH  /api/projects/:id
DELETE /api/projects/:id

路径表示资源,方法表示动作。这样接口结构更统一,也更容易被别人理解。

请求参数要分清位置

接口请求参数通常有三类:路径参数、查询参数和请求体。

路径参数用于定位资源,比如 /api/projects/123 里的 123。查询参数用于筛选、搜索、排序和分页,比如 ?status=active&page=1。请求体用于提交创建或更新的数据。

不要把所有参数都塞进请求体,也不要把复杂数据塞进 URL。

一个清晰的规则是:定位资源放路径,控制列表放查询,提交数据放请求体。

响应结构要稳定

接口返回给前端的数据结构要尽量稳定。不要今天返回数组,明天返回对象;成功时一个结构,失败时另一个完全不相关的结构。

一个常见的成功响应可以是:

{
  "data": {
    "id": "project_123",
    "name": "Demo Project",
    "status": "active"
  }
}

列表响应可以包含分页信息:

{
  "data": [
    { "id": "project_123", "name": "Demo Project" }
  ],
  "pagination": {
    "page": 1,
    "pageSize": 20,
    "total": 128
  }
}

稳定的响应结构,会让前端少写很多特殊判断。

错误响应要能帮助定位问题

接口失败时,不要只返回“失败”或“服务器错误”。

错误响应至少要包含错误码、可读信息和必要的字段信息。比如:

{
  "error": {
    "code": "PROJECT_NAME_REQUIRED",
    "message": "Project name is required.",
    "field": "name"
  }
}

前端可以根据 code 做逻辑判断,根据 message 展示提示,根据 field 高亮表单字段。

好的错误设计,不只是为了开发者,也是为了用户体验。

输入必须校验

不要相信前端传来的任何数据。

即使前端已经限制了字段长度、格式和必填项,后端仍然必须重新校验。因为接口可以被绕过,用户也可以直接请求 API。

校验至少包括:必填字段、字段类型、长度限制、枚举值、数字范围、文件大小、权限范围、业务规则。

输入校验越早越清楚,后面的数据污染越少。

鉴权和权限要分开看

鉴权回答“你是谁”,权限回答“你能不能做这件事”。

很多新手只判断用户是否登录,却忘了判断用户是否有权限操作某个资源。

比如用户登录了,不代表他能删除别人的项目;团队成员能查看项目,不代表他能修改账单;普通用户能上传文件,不代表他能访问管理员接口。

每个涉及用户数据的接口,都要同时考虑鉴权和权限。

接口要考虑幂等性

幂等性指同一个请求执行多次,结果不会产生意外副作用。

比如用户点击“保存设置”两次,不应该生成两份设置;支付回调收到两次,不应该创建两张订单;删除同一个资源多次,不应该导致系统异常。

不是所有接口都天然幂等,但重要接口要提前设计。

尤其是支付、订单、Webhook、后台任务、批量操作,一定要考虑重复请求。

列表接口要从一开始支持分页

不要让列表接口一次返回所有数据。

早期数据少时看不出问题,后面数据一多,接口会变慢,页面会卡,数据库压力会变大。

列表接口应该从一开始支持分页、排序和必要筛选。即使当前只有几条数据,也要保留结构。

比如:

GET /api/projects?page=1&pageSize=20&status=active&sort=createdAt_desc

这会让未来扩展更自然。

不要过早设计复杂版本号

很多人第一次写 API 就开始设计 /api/v1/api/v2、复杂版本策略。

如果你的 API 只服务自己的前端,早期不一定需要复杂版本管理。更重要的是保持响应结构稳定,避免随意破坏字段含义。

如果你的 API 会开放给第三方,或者会被多个客户端长期使用,就需要更认真地设计版本、兼容策略和弃用流程。

版本号不是越早越专业,而是要看使用边界。

文档要跟接口一起写

接口文档不需要一开始很华丽,但必须能说明:接口做什么,请求参数是什么,响应是什么,错误有哪些,权限要求是什么。

最简单的文档也可以是:

POST /api/projects
作用:创建项目
权限:登录用户
请求体:name, description
成功:返回项目详情
错误:PROJECT_NAME_REQUIRED, PROJECT_LIMIT_EXCEEDED

文档的价值不是形式,而是减少沟通成本。半年后你自己也会感谢当时写清楚了。

一个第一个接口模板

你可以用下面模板设计接口:

接口名称:
用户动作:
资源对象:
HTTP 方法:
路径:
路径参数:
查询参数:
请求体:
权限要求:
成功响应:
错误响应:
是否需要幂等:
是否需要分页:
是否需要日志:

每次写接口前先填这张表,能避免很多随手设计。

写在最后

第一个接口的目标不是炫技,而是建立稳定的契约。

路径清楚、参数清楚、响应稳定、错误可读、权限明确、文档同步,这些基础做好,后面的功能才会越写越顺。

下一篇,我们继续聊接口和外部系统:Webhook 实战

正文到此结束
Loading...