API设计是那些原则已经确立但实践中被广泛忽视的学科之一。以下是构建其他开发者会想使用的API真正重要的事情。
正确的RESTful设计
大多数API声称是RESTful;很少实际上是。最常被违反的关键原则:面向资源的URL(名词,不是动词):`/users/123/orders`是REST;`/getUserOrders?userId=123`是伪装成REST的RPC。URL标识资源;HTTP方法表达动作。正确的HTTP方法:GET(幂等、可缓存、无主体);POST(创建新资源,不幂等);PUT(完全替换资源,幂等);PATCH(部分更新,主体只包含要更改的字段);DELETE(删除资源,幂等)。表达其含义的状态码:200 OK(带主体的成功);201 Created(资源已创建,包含指向新资源的Location头);204 No Content(没有主体的成功——DELETE响应);400 Bad Request(客户端错误——无效输入);401 Unauthorized(需要认证);403 Forbidden(已认证但未授权);404 Not Found;409 Conflict(状态冲突——创建重复的唯一资源);422 Unprocessable Entity(有效的JSON但业务验证失败);429 Too Many Requests(速率限制);500 Internal Server Error。常见错误:返回200 OK with `{“success”: false, “error”: “not found”}`而不是404。这会破坏所有HTTP工具(缓存、代理、监控)。
响应设计
一致的错误格式:每个错误响应应该有相同的结构——`{“error”: {“code”: “USER_NOT_FOUND”, “message”: “No user with id 123 exists”, “details”: {…}}}`。`code`字段允许客户端以编程方式处理特定错误;`message`是为人类和日志记录。分页:对于列表端点,始终分页;永远不要返回无界列表。两种常见方法:偏移/限制(`?offset=0&limit=20`)——简单,允许跳到第N页;基于游标(`?after=eyJ…`)——对大数据集和实时数据更好(即使在分页期间添加数据也保持一致)。在响应中包含分页元数据(`{“data”: […], “pagination”: {“total”: 1234, “next_cursor”: “eyJ…”}}`)。版本控制:URL路径版本(`/v1/users`)是最实际的方法——清晰、易于路由、明确。头版本(`Accept: application/vnd.myapi.v1+json`)理论上是更纯粹的REST,但操作上更难。废弃:在废弃端点上设置`Sunset`和`Deprecation`头以提前通知客户端。
真正使API好用的东西
带示例的文档:每个端点都应该有请求示例和响应示例。抽象描述没用;具体示例使API可用。认证清晰性:明确说明认证如何工作、令牌看起来像什么、如何刷新它们,以及它们过期时会发生什么。幂等键:对于不应该被重复的POST端点(支付处理、订单创建),支持幂等键——客户端提供的UUID在头中,服务器使用它来检测并返回重复请求的原始响应。速率限制透明度:在响应中包含`X-RateLimit-Limit`、`X-RateLimit-Remaining`和`X-RateLimit-Reset`头,让客户端知道他们的使用情况并可以实现退避。最常见的API设计错误:不一致。一个API中一些资源使用驼峰命名法,一些蛇形命名法,一些使用`id`,一些`uuid`,错误格式因端点而异,分页在端点之间以不同方式实现,比起一个有不完美但一致约定的API更难使用。


