3. HTTP 基础回顾:请求方法、状态码、请求头与响应头、RESTful API 设计原则

在深入 Go 语言的 API 契约校验之前,必须牢固掌握 HTTP 协议的核心要素。本章将系统回顾 HTTP 请求方法、状态码、头部字段以及 RESTful API 的设计原则,为后续的契约定义与校验打下坚实基础。

3.1 HTTP 请求方法

HTTP 请求方法(也称为 HTTP 动词)定义了客户端对服务器资源期望执行的操作。在 RESTful API 设计中,常用的方法有五种:

方法 语义 幂等性 安全性 请求体
GET 获取资源 是 是 无
POST 创建资源 否 否 有
PUT 整体更新/替换资源 是 否 有
PATCH 部分更新资源 否 否 有
DELETE 删除资源 是 否 通常无
幂等性要点: 幂等方法意味着多次执行与单次执行对服务器资源产生的副作用相同。例如,多次 DELETE /users/123 的结果都是资源被删除(或返回 404),但多次 POST /users 会创建多个用户,因此不幂等。

3.2 HTTP 状态码

状态码是服务器对请求结果的标准化响应。按类别分为五大类,API 设计中常用的状态码如下:

类别 范围 常用状态码 含义
1xx 100-199 100 Continue 信息性响应,客户端应继续发送请求体
2xx 200-299 200 OK
201 Created
204 No Content
请求成功
资源创建成功
删除/更新成功,无响应体
3xx 300-399 301 Moved Permanently
304 Not Modified
重定向
资源未修改(用于缓存)
4xx 400-499 400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
409 Conflict
422 Unprocessable Entity
客户端错误
未认证
无权限
资源不存在
资源冲突(如重复创建)
请求体校验失败
5xx 500-599 500 Internal Server Error
503 Service Unavailable
服务器内部错误
服务暂时不可用
契约校验关注点: 在定义 API 契约时,必须明确每个端点可能返回的所有状态码及其对应的响应结构。例如,POST /orders 成功应返回 201 Created,而校验失败应返回 422 Unprocessable Entity 并附带错误详情。

3.3 请求头与响应头

HTTP 头部字段用于传递元数据,是契约校验中不可忽视的部分。以下是与 API 契约密切相关的常用头部:

3.3.1 常见请求头

  • Content-Type:请求体的媒体类型,如 application/json、application/xml。
  • Accept:客户端期望的响应媒体类型。
  • Authorization:认证凭证,如 Bearer <token>。
  • X-Request-ID:用于链路追踪的请求唯一标识。

3.3.2 常见响应头

  • Content-Type:响应体的媒体类型。
  • Location:创建资源后的 URI,通常与 201 Created 配合使用。
  • Cache-Control:缓存策略指令。
  • X-RateLimit-Remaining:API 限流剩余次数。
契约校验实践: 在 Go 中,使用 net/http 标准库时,可通过 r.Header.Get("Content-Type") 获取请求头,通过 w.Header().Set("X-Request-ID", uuid) 设置响应头。契约测试框架(如 pact-go)允许精确匹配头部字段。

3.4 RESTful API 设计原则

REST(Representational State Transfer)是一种架构风格,其核心原则指导着现代 API 的设计。以下是六大关键原则:

  1. 资源导向:一切皆资源,使用名词而非动词命名端点,如 /users 而非 /getUsers。
  2. 无状态:每个请求包含所有必要信息,服务器不保存客户端上下文。
  3. 统一接口:使用标准 HTTP 方法(GET/POST/PUT/PATCH/DELETE)操作资源。
  4. 可寻址性:每个资源有唯一的 URI,如 /users/123。
  5. 表现层状态:客户端通过请求头 Accept 和 Content-Type 协商资源的表现形式(JSON/XML)。
  6. 超媒体驱动(HATEOAS):响应中包含相关资源的链接,引导客户端发现下一步操作。

以下 SVG 图展示了 RESTful API 的核心交互流程:

RESTful API 核心交互流程 RESTful API 核心交互流程 客户端 服务器 资源层 数据库 HTTP 请求 (GET/POST/PUT/DELETE) HTTP 响应 (200/201/404/422) 路由到资源 持久化 核心原则体现: • 资源导向:URI 表示资源,方法表示操作 • 无状态:每个请求独立,服务器不保存会话 • 统一接口:标准方法 + 标准状态码

3.5 RESTful API 端点设计示例

以下是一个典型的用户管理 API 端点设计,展示了如何将上述原则落地:

方法 端点 描述 成功状态码 请求体示例
GET /users 获取用户列表 200 OK 无
GET /users/{id} 获取单个用户 200 OK 无
POST /users 创建新用户 201 Created
{
  "name": "张三",
  "email": "zhangsan@example.com"
}
PUT /users/{id} 整体更新用户 200 OK
{
  "name": "李四",
  "email": "lisi@example.com"
}
PATCH /users/{id} 部分更新用户 200 OK
{
  "email": "newemail@example.com"
}
DELETE /users/{id} 删除用户 204 No Content 无
命名规范: 端点使用复数名词(/users 而非 /user),路径参数使用小写字母和连字符(/order-items 而非 /orderItems)。查询参数用于过滤、排序和分页,如 /users?page=1&size=20&sort=name。

3.6 契约校验中的 HTTP 要素

在 Go 的契约测试中,以下 HTTP 要素是校验的核心对象:

  • 请求方法 + 路径:构成端点的唯一标识。
  • 请求头:特别是 Content-Type 和 Authorization。
  • 请求体:JSON Schema 或 Protobuf 定义的结构。
  • 响应状态码:每个端点必须明确所有可能的返回码。
  • 响应头:如 Location、Content-Type。
  • 响应体:与请求体对应的结构定义。

以下 SVG 图展示了契约校验如何覆盖 HTTP 请求-响应的完整生命周期:

契约校验覆盖的 HTTP 要素 契约校验覆盖的 HTTP 要素 请求 (Request) • 方法: GET / POST / PUT / DELETE • 路径: /users/{id}?page=1 • 请求头: Content-Type, Authorization • 请求体: JSON / XML / Protobuf 响应 (Response) • 状态码: 200 / 201 / 404 / 422 • 响应头: Location, Content-Type • 响应体: 结构、字段类型、枚举值 • 错误详情: code, message, details 契约校验引擎 校验目标:确保请求与响应完全符合预定义的契约规范,包括方法、路径、头部、状态码和体结构。
Go 实战提示: 在 Go 中,可以使用 net/http/httptest 包模拟 HTTP 请求与响应,结合 encoding/json 进行序列化/反序列化。契约测试框架(如 pact-go 或 go-restful)会自动生成请求-响应匹配规则,开发者只需定义契约文件即可。