什么是 REST?
REST(Representational State Transfer,表述性状态转移)是一种架构风格,而非协议。它定义了一组约束,用于规定 Web 服务的行为方式。当 API 遵循这些约束时,我们称之为 RESTful。其核心理念很简单:客户端向一个代表资源的 URL 发送请求,服务器以该资源的表述形式(通常是 JSON)进行响应。
定义 REST 的六大约束分别是:客户端-服务器分离、无状态、可缓存、统一接口、分层系统,以及按需代码(可选)。在实际日常开发中,最重要的是无状态和统一接口。无状态意味着每个请求都必须包含处理该请求所需的全部信息——服务器不会在请求之间存储会话状态。统一接口则意味着使用标准的 HTTP 方法和可预测的 URL 模式。
HTTP 方法及其含义
HTTP 方法告诉服务器要对资源执行什么操作。每个方法都带有特定的语义含义,你应当遵循——忽略这一点会导致 API 难以理解和使用。
GET 用于读取资源,不会产生副作用。POST 用于创建新资源。PUT 用于完整替换现有资源。PATCH 用于对资源进行部分更新。DELETE 用于删除资源。
以下是这些方法在典型的 users 资源上的对应方式:
GET 和 DELETE 是幂等的——多次调用它们产生的结果相同。PUT 也是幂等的。POST 则不是——调用两次通常会创建两个资源。
HTTP 状态码
状态码告诉客户端发生了什么。状态码分为五类:1xx 信息提示、2xx 成功、3xx 重定向、4xx 客户端错误、5xx 服务器错误。在 API 开发中最常用的有:
200 OK —— 请求成功,且有响应体。用于成功的 GET 和 PATCH 响应。
201 Created —— 资源已成功创建。在 POST 成功后使用,并应包含一个指向新资源的 Location 头。
204 No Content —— 成功,但没有响应体返回。用于 DELETE 操作。
400 Bad Request —— 客户端发送了无效数据(缺少字段、类型错误、校验失败)。
401 Unauthorized —— 请求缺少有效的身份验证凭证。
403 Forbidden —— 客户端已通过身份验证,但没有相应权限。
404 Not Found —— 资源不存在。
409 Conflict —— 请求与当前状态冲突(例如,使用已存在的邮箱创建用户)。
422 Unprocessable Entity —— 请求格式正确,但语义校验失败。
500 Internal Server Error —— 服务器端发生了错误。在生产环境中切勿暴露堆栈信息。
Express 处理器中的一个具体示例:
API 场景下的 HTTP 请求头
请求头携带有关请求或响应的元数据。其中有一些对于 REST API 至关重要。
Content-Type 用于声明请求或响应体的格式。对于 JSON API,这始终是 application/json。Express 在调用 res.json() 时会自动设置该头,但在构建原始响应时,你必须显式设置它。
Accept 用于告知服务器客户端能够处理的数据格式。客户端在调用 JSON API 时应发送 Accept: application/json。
Authorization 用于携带凭证。REST API 最常见的模式是 Bearer token 身份验证:
Cache-Control 用于指定 GET 响应的缓存策略。对于很少变化的公共数据,设置 Cache-Control: public, max-age=300 可以减轻服务器负载。对于与用户相关或敏感数据,则应使用 Cache-Control: no-store。
在 Express 中,你可以通过 req.headers 读取传入的请求头,并通过 res.set() 设置传出的响应头:
小结
REST 是一种基于无状态客户端-服务器通信与统一接口的架构风格。HTTP 方法定义了对资源执行的操作——GET 用于读取、POST 用于创建、PUT 用于替换、PATCH 用于更新、DELETE 用于删除。状态码精确地传达结果:2xx 表示成功,4xx 表示客户端错误,5xx 表示服务器故障。请求头携带诸如内容类型、身份验证凭证和缓存指令等元数据。正确掌握这些基础知识,是区分一个易于集成的 API 与一个迫使使用者反复猜测的 API 的关键所在。
课程检查点