restful规范

发布于:2025-06-30 ⋅ 阅读:(22) ⋅ 点赞:(0)

RESTful 是一种基于 REST 架构风格设计的 API 规范。REST 是 REpresentational State Transfer(表现层状态转换)的缩写,由 Roy Fielding 博士在其博士论文中提出。它描述了 Web 服务应该如何设计,以便它们易于理解、可扩展、可靠,并能充分利用 HTTP 协议的特性。

遵循 RESTful 规范设计的 API 被称为 RESTful API。这些规范不是强制标准,但遵循它们能让 API 更清晰、更易用、更健壮。

以下是 RESTful API 设计的核心规范和实践:
以资源为中心

API 应围绕资源(Resource)进行设计。资源可以是应用程序中的任何实体或概念,如用户、订单、产品、文章等。

每个资源都应该有一个唯一的标识符(URI/URL)。

URI 设计原则:

使用名词复数形式: /users, /orders, /products 而不是 /getUser, /createOrder。

清晰明确: URI 应该直观地反映其代表的资源。

层级关系: 使用路径表示资源间的层级关系。例如,用户的所有订单:/users/{userId}/orders。

避免动词: URI 应标识资源,操作由 HTTP 方法表示。错误示例:/users/{id}/update。

版本控制: 通常在 URI 或 Header 中加入版本号(如 /v1/users 或 Accept: application/vnd.myapi.v1+json)。

可读性: 使用连字符 - 分隔单词,如 /product-categories。避免下划线 _ 或驼峰式。

扩展性: 考虑未来可能的资源嵌套和扩展。
利用 HTTP 方法(Verbs)

核心操作对应标准 HTTP 方法:

GET: 检索一个或多个资源。安全(Safe)且幂等(Idempotent)。

GET /users - 获取所有用户列表

GET /users/{id} - 获取特定 ID 的用户

POST: 创建一个新的资源。非安全、非幂等。

POST /users - 创建一个新用户(请求体包含用户数据)

PUT: 替换或完整更新一个已存在的资源(需要提供完整的资源表示)。如果资源不存在,有时可以创建(需文档说明)。安全?非安全(修改资源),幂等。

PUT /users/{id} - 更新(或创建)指定 ID 的用户(请求体包含完整的用户数据)

PATCH: 对资源进行部分更新(只需要提供需要更改的字段)。安全?非安全,幂等性依赖于实现方式(通常实现应保证幂等,但标准不强制)。

PATCH /users/{id} - 部分更新指定 ID 的用户(请求体仅包含要修改的字段)

DELETE: 删除一个资源。安全?非安全,幂等(第一次删除成功,后续删除虽然返回 404 或 204,但资源状态未变)。

DELETE /users/{id} - 删除指定 ID 的用户

其他 HTTP 方法: HEAD(类似 GET,只获取头部信息), OPTIONS(查询服务器支持的 HTTP 方法)也常用于 API。CONNECT, TRACE 在 Web API 中使用较少。
无状态性

每个请求都必须包含服务器处理该请求所需的所有信息。服务器不应在请求之间存储客户端的状态上下文。

会话状态应完全保存在客户端(例如,通过 Token、API Key 或包含在请求中)。这使得服务器易于扩展(只需添加更多实例),提高了可靠性和可见性。

如果需要“登录”,认证信息(Token、API Key、JWT 等)应包含在每个请求的 Header(如 Authorization)中。
表述(Representation)

资源与客户端交互时,是以其表述的形式存在的。

同一资源可以有多种表述格式,如 JSON, XML, YAML, HTML, 纯文本 等。现代 API 主要使用 JSON。

客户端和服务端通过 HTTP Header 协商表述格式:

Content-Type: 请求头(用于 POST, PUT, PATCH)和响应头(服务器返回的格式),如 application/json。

Accept: 请求头,客户端声明它希望接受的响应格式,如 Accept: application/json。

清晰的 JSON 结构:键名使用小写蛇形命名(snake_case)或小写驼峰(camelCase),避免无谓的嵌套。
使用标准的 HTTP 状态码(Status Codes)

使用适当的 HTTP 状态码来传达请求的结果,让客户端能快速理解发生了什么。避免所有响应都用 200 OK 但包含错误信息体。

常用状态码类别:

2xx 成功 (Success):

200 OK - 标准成功响应(GET, PUT, PATCH)。

201 Created - 资源创建成功(通常用于 POST)。响应头 Location 应包含新资源的 URI。

202 Accepted - 请求已被接收,但处理尚未完成(常用于异步操作)。

204 No Content - 操作成功,但响应体无内容(常用于 DELETE 或不需返回数据的 PUT)。

3xx 重定向 (Redirection): API 较少直接使用。

4xx 客户端错误 (Client Error):

400 Bad Request - 通用客户端错误,服务器无法处理(例如格式错误的请求体)。

401 Unauthorized - 未认证,需要有效的凭证。

403 Forbidden - 已认证但无权限访问该资源。

404 Not Found - 请求的资源不存在。

405 Method Not Allowed - 该 URI 不支持请求的 HTTP 方法。

406 Not Acceptable - 服务器无法生成 Accept 头请求的格式。

409 Conflict - 请求与服务器当前状态冲突(如更新一个已被他人更新的资源)。

415 Unsupported Media Type - 请求实体的媒体类型(Content-Type)不受支持。

422 Unprocessable Entity (WebDAV) - 请求格式正确,但语义错误(如验证失败)。

5xx 服务端错误 (Server Error):

500 Internal Server Error - 服务器内部错误,通用错误。

501 Not Implemented - 服务器不支持该功能。

503 Service Unavailable - 服务器暂时无法处理请求(如过载、维护)。
在响应体中提供丰富的错误信息

仅使用状态码通常不够清晰,应在错误响应的 Body 中提供:

error_code: 应用程序特定的、机器可读的错误代码(可选但推荐)。

message: 清晰、人性化的错误描述,帮助开发者理解问题。

details: 更详细的信息,如验证错误列表([{field: “name”, message: “is required”}])。

documentation_url: 指向相关文档的链接(可选但非常有用)。

使用一致的 JSON 结构表示错误。
过滤、排序、分页和字段选择

对于返回集合的 GET 请求(如 /users),通常需要:

过滤 (Filtering): 使用查询参数指定条件,如 GET /users?role=admin

排序 (Sorting): 使用如 sort 参数,如 GET /users?sort=-created_at,name (以 - 表示降序)。

分页 (Pagination): 必须提供,避免返回过多数据。使用参数如 limit (或 page_size) 和 offset (或 page) / cursor。

响应中应包含分页元数据(total_count, offset, limit, links to next/prev/first/last page)。例如: {“data”: […], “pagination”: {“total”: 100, “offset”: 20, “limit”: 10}}。

字段选择 (Field Selection/Faceets): 允许客户端指定返回哪些字段,提高效率,如 GET /users?fields=id,name,email。

参数名称应语义清晰、一致。
HATEOAS(可选但推荐用于复杂或发现式 API)

Hypermedia as the Engine of Application State。在响应中包含指向相关资源的超媒体链接(在 JSON 中通常是 _links 对象或类似结构)。

客户端可以通过这些链接“发现”和导航 API,而无需硬编码 URL 路径结构。

例如,一个用户资源的响应可能包含指向其订单、头像等的链接:

    "id": 123,

      "name": "Alice",
      "email": "alice@example.com",
      "_links": {
        "self": { "href": "https://api.example.com/users/123" },
        "orders": { "href": "https://api.example.com/users/123/orders" },
        "avatar": { "href": "https://cdn.example.com/avatars/123.png" }

}

好处:解耦客户端与服务器 URL 结构,提高 API 的自我描述性和可演化性。但增加了实现复杂性和响应体大小。
API 文档

清晰、完整、最新的文档是 RESTful API 成功的关键!

文档应包括:

所有资源端点及其 URI。

每个端点支持的 HTTP 方法。

请求和响应的格式(Schema),包括 Header、参数(路径、查询、请求体)、可能的响应状态码和示例。

认证/授权要求。

分页、过滤、排序等的规则。

错误代码和格式。

推荐使用 OpenAPI (Swagger) 规范生成机器可读的文档和交互式探索界面。
版本控制

当需要对 API 进行不兼容的更改时,必须使用版本控制。

常见方法:

URI 路径中 (/v1/users): 最常用且直观。

自定义请求头 (Accept: application/vnd.myapi.v1+json): 更符合 REST 无版本 URI 的理念,但实现略复杂。

查询参数 (/users?version=1): 不太推荐,语义不清晰且影响缓存。

为不同的主要版本维护独立的行为。在一个主版本内通过小版本进行向后兼容的扩展(如添加非必需字段、添加可选端点)。
安全性

始终使用 HTTPS。

实现健壮的认证(Authentication) 机制(如 API Key、OAuth 2.0、JWT)。

实施严格的授权(Authorization) 控制(RBAC, ABAC 等)。

处理 CORS(如果 API 被浏览器访问)。

输入验证: 严格验证所有输入(请求体、查询参数、路径参数)。

速率限制(Rate Limiting): 防止滥用和 DoS 攻击(通常通过 X-RateLimit-* 响应头告知客户端限制信息)。

数据保护: 避免暴露敏感数据。

最佳实践总结 & 常见误区避免:
保持一致性: 整个 API 使用相同的命名规则(URI、参数、字段)、状态码、错误格式。

KISS (Keep It Simple): 避免过度设计(过度嵌套资源、过早抽象)。

资源优先: 始终围绕资源进行设计。

URI 是名词,HTTP 方法是动词: 不要在 URI 中使用动词(/createUser)。

使用复数名词: GET /users。

正确使用 HTTP 方法: 区分 PUT(替换)和 PATCH(部分更新),区分 401 和 403。

文档即契约: 认真对待文档,并保持更新。

拥抱版本控制: 计划好如何应对变化。

测试: 编写全面的单元测试、集成测试和端到端测试。

遵循这些 RESTful 规范,你可以设计和构建出高效、易于理解、可维护且能良好协作的 Web API。记住,规范是指导,核心原则(资源中心、HTTP语义、无状态)比教条地遵守每个细节更重要。根据你的具体业务场景和团队偏好做适当的调整。


网站公告

今日签到

点亮在社区的每一天
去签到