什么是好的API
API(Application Programming Interface 应用程序编程接口)是不同软件系统之间通信的契约。在现代Web开发中 前端(网页/小程序/APP)通过API与后端服务交互 几乎所有的业务逻辑都围绕API展开。一个好的API应该具备以下特质:清晰易懂——开发者看到API文档就能立刻理解每个接口的作用和使用方式 不需要额外的口头解释;一致性强——所有接口遵循相同的设计规范和命名惯例 学习一个接口后可以举一反三;健壮可靠——有完善的错误处理机制 异常情况有明确的错误信息和状态码;安全可控——有适当的认证授权机制 敏感操作有权限校验;易于演化——支持版本管理 新功能的加入不影响现有客户端。下面我们从各个方面详细讨论如何设计出满足上述特质的RESTful API。
URL设计原则
RESTful API的核心思想是"一切皆资源" 每个URL代表一种资源 URL中应该只包含名词(资源名称) 不应该包含动词(动作)。URL应该是名词复数形式。正例:GET /api/users(获取用户列表) POST /api/orders(创建订单) GET /api/products/123(获取ID为123的产品)。反例:GET /api/getUsers(URL中含有动词) POST /api/createOrder(同上) GET /api/product(单数形式 不一致)。层级关系通过嵌套URL表达:GET /api/users/456/orders(获取用户456的订单列表) GET /api/users/456/orders/789(获取用户456的订单789详情)。但层级不宜过深(建议不超过3层) 过深的嵌套可以考虑使用查询参数代替:GET /api/orders?user_id=456&status=pending。查询参数用于过滤 排序 分页和字段选择:过滤:GET /api/products?category=food&price_min=10&price_max=100;排序:GET /api/products?sort=price&order=asc(升序) GET /api/products?sort=created_at&order=desc(降序 最新在前);分页:GET /api/products?page=2&page_size=20(第2页 每页20条) 响应中应包含分页元数据:{"data": [...], "pagination": {"total": 200, "page": 2, "page_size": 20, "total_pages": 10}};字段选择:GET /api/users?fields=id,name,email(只返回这三个字段 减少传输量)。
HTTP方法语义的正确使用
GET:获取资源 幂等的(多次调用结果相同) 安全的(不产生副作用)。GET请求不应该有body参数(虽然HTTP协议不禁止 但这是不良实践 所有参数应放在URL query string中)。POST:创建子资源 非幂等的(调用两次会创建两个资源)。例如:POST /api/users 创建新用户 POST /api/orders 创建新订单。PUT:全量替换资源(幂等的)。例如:PUT /api/users/456 完整替换用户456的所有信息(请求体需包含所有必填字段)。PATCH:部分更新资源(非幂等的 通常)。例如:PATCH /api/users/456 {"email": "new@example.com"} 只更新email字段。DELETE:删除资源(幂等的)。例如:DELETE /api/users/456 删除用户456。特别注意幂等性概念:GET PUT DELETE应该是幂等的——同样的请求执行一次和执行N次 结果应该相同(对于DELETE 第一次删除返回200 第二次返回404 Not Found 但服务器的最终状态是一样的 所以仍是幂等的)。POST是非幂等的——每次调用都会创建新资源。
状态码规范
正确使用HTTP状态码是API专业性的重要体现。常用的状态码分类:2xx(成功):200 OK——通用成功响应(GET PUT PATCH);201 Created——资源创建成功(POST);204 No Content——成功但无返回体(DELETE)。3xx(重定向):304 Not Modified——资源未修改(配合If-None-Match/If-Modified-Since头使用 用于缓存)。4xx(客户端错误):400 Bad Request——请求参数有误(如必填字段缺失 格式错误);401 Unauthorized——未认证(缺少或无效的token);403 Forbidden——已认证但无权限;404 Not Found——资源不存在;405 Method Not Allowed——HTTP方法不允许;409 Conflict——资源冲突(如创建重复的唯一字段值);422 Unprocessable Entity——语义正确但无法处理(如验证失败 通常用于表单验证错误的响应);429 Too Many Requests——频率超限(Rate Limiting)。5xx(服务端错误):500 Internal Server Error——服务器内部错误;502 Bad Gateway——网关/代理错误;503 Service Unavailable——服务暂时不可用(维护中)。最佳实践:永远不要在业务逻辑正常的情况下返回200然后在body里放{"code": 400, "message": "参数错误"}——这是反模式 应该直接使用对应的HTTP状态码;错误响应体应该包含有用的调试信息:{"error": {"code": "INVALID_EMAIL", "message": "邮箱格式不正确", "details": {"field": "email", "value": "abc"}}}。
认证 授权与安全
认证(Authentication)——确认"你是谁"。推荐方式:JWT(JSON Web Token)——无状态认证 适合分布式架构。登录成功后服务端签发JWT token 客户端后续每次请求在Authorization头中携带:Bearer 。Token中应包含:sub(用户ID) exp(过期时间) iat(签发时间) role(角色 可选)。Token有效期建议:Access Token 15分钟到2小时 Refresh Token 7天到30天。授权(Authorization)——确认"你能做什么"。推荐方式:RBAC(Role-Based Access Control 基于角色的访问控制)。在JWT中加入role字段 或者在后端中间件中根据用户角色判断是否有权限访问当前资源。常见的角色划分:admin(管理员 可读写所有资源) editor(编辑者 可读写自己负责的资源) viewer(只读者 只能GET)。其他安全要点:所有API必须强制使用HTTPS(HTTP明文传输token等于裸奔);实施Rate Limiting(速率限制)防止暴力破解和DDoS——如每IP每分钟最多100次请求 超出返回429;输入验证永远不能少——即使用了JWT认证 也要对所有输入参数做校验(长度 类型 格式 白名单等) 防止SQL注入 XSS等攻击;敏感操作(如删除 修改密码 变更权限)应要求二次确认或re-authentication(重新输入密码)。
版本管理与文档
API一定会演化——新增字段 修改接口结构 废弃旧接口等。版本管理策略:URL路径版本(推荐):/api/v1/users /api/v2/users 简单明确 客户端可以自主选择版本。Accept Header版本:在请求头中指定 Accept: application/vnd.myapi.v2+json 更RESTful纯粹 但不够直观。不建议的做法:不在URL中放版本 且直接修改已有接口的行为——这会导致旧客户端突然全部出错。API文档是必不可少的。推荐工具:Swagger/OpenAPI(目前最流行的API文档规范)——使用注解或YAML文件定义API规范 自动生成交互式文档页面(Swagger UI)。Python FastAPI自带OpenAPI支持;Node.js Express可用swagger-jsdoc + swagger-ui-express;Java Spring Boot可用springdoc-openapi。文档中应包含:每个接口的URL HTTP方法 参数说明(路径参数 查询参数 请求体字段及其类型和是否必填) 所有可能的响应状态码及其含义 认证方式说明 使用示例(curl命令或代码示例)。对于{CS}的开发团队来说 养成"先写文档再写代码"或"边写代码边更新文档"的习惯 将大大提升前后端协作效率和API的可维护性。一份清晰完整的API文档是你送给调用者(包括未来的你自己)最好的礼物。