3. 接口校验基础:HTTP 协议回顾、请求方法、状态码与报文结构
接口校验是压测用例的“裁判员”。没有校验,压测只是空转。而校验的根基,是 HTTP 协议。本章从后端测试视角,快速回顾 HTTP 的核心要素:请求方法、状态码、请求头与响应体结构。这些知识将直接用于后续的 Testing 断言与压测指标设计。
3.1 HTTP 协议核心要素
HTTP(HyperText Transfer Protocol)是客户端与服务端之间无状态的请求-响应协议。一次完整的 HTTP 交互包含以下要素:
- 请求行:方法 + URI + 协议版本
- 请求头:元数据,如 Content-Type、Authorization
- 请求体:POST/PUT 携带的数据
- 状态行:协议版本 + 状态码 + 原因短语
- 响应头:服务端返回的元数据
- 响应体:服务端返回的数据
压测视角: 压测工具(如 k6、wrk、Locust)本质上是构造 HTTP 请求并收集响应。理解报文结构,才能精准设置请求参数和断言条件。
3.2 请求方法:CRUD 的 HTTP 映射
RESTful 接口中,请求方法对应资源的操作类型。压测用例必须为每个接口选择正确的方法,否则校验必然失败。
| 方法 | 语义 | 幂等 | 请求体 | 典型状态码 | 压测场景 |
|---|---|---|---|---|---|
| GET | 查询资源 | 是 | 无 | 200 | 读接口压测,关注响应时间与数据正确性 |
| POST | 创建资源 | 否 | 有 | 201 / 400 | 写接口压测,关注重复提交与数据一致性 |
| PUT | 全量更新 | 是 | 有 | 200 / 204 | 更新接口压测,关注幂等性校验 |
| DELETE | 删除资源 | 是 | 无 | 204 / 404 | 删除接口压测,关注资源不存在时的处理 |
| PATCH | 部分更新 | 否 | 有 | 200 / 400 | 部分更新压测,关注字段级校验 |
幂等性陷阱: 压测中重复发送 POST 请求可能产生重复数据。测试用例应设计幂等键(Idempotency-Key)或使用 PUT 替代 POST 来避免脏数据。
3.3 状态码:接口健康的“红绿灯”
状态码是服务端对请求的“判决”。压测校验的第一步就是断言状态码是否符合预期。以下是后端测试中最常遇到的分类:
- 2xx 成功
200 OK:GET、PUT、PATCH 成功201 Created:POST 创建成功204 No Content:DELETE 成功,无响应体
- 3xx 重定向
301 Moved Permanently:资源永久迁移302 Found:临时重定向304 Not Modified:缓存未过期
- 4xx 客户端错误
400 Bad Request:参数校验失败401 Unauthorized:未认证403 Forbidden:无权限404 Not Found:资源不存在429 Too Many Requests:限流触发
- 5xx 服务端错误
500 Internal Server Error:服务内部异常502 Bad Gateway:网关/代理错误503 Service Unavailable:服务过载或维护504 Gateway Timeout:上游超时
压测校验红线: 压测期间,5xx 状态码占比应严格为 0%。如果出现 429,说明限流策略生效,需评估限流阈值是否合理。4xx 状态码需区分是测试数据问题还是接口逻辑缺陷。
3.4 请求头与响应体结构
接口校验不仅看状态码,还要验证请求头与响应体的内容。以下是后端测试中最关键的字段:
3.4.1 常见请求头
| 请求头 | 说明 | 压测校验点 |
|---|---|---|
Content-Type |
请求体格式,如 application/json |
必须与服务端期望一致 |
Authorization |
认证令牌,如 Bearer <token> |
压测前需获取有效 token,关注过期时间 |
Accept |
客户端期望的响应格式 | 确保服务端返回正确的 Content-Type |
X-Request-Id |
请求追踪 ID | 用于链路追踪,压测中应生成唯一值 |
Idempotency-Key |
幂等键,防止重复提交 | POST 压测时建议携带 |
3.4.2 响应体结构校验
响应体通常是 JSON 格式。压测用例需要校验以下维度:
- 字段存在性:关键字段是否返回(如
id、status) - 字段类型:
string、number、boolean、array、object - 字段值范围:数值是否在合理区间,字符串是否为空
- 嵌套结构:深层 JSON 对象的层级是否正确
- 数组长度:分页接口的
items数组长度是否与pageSize一致
// 示例:用户列表接口响应体校验
{
"code": 200, // 业务状态码
"message": "success",
"data": {
"total": 100, // 总数,必须为 number
"page": 1, // 当前页,必须为 number
"pageSize": 10, // 每页条数,必须为 number
"items": [ // 数组,长度 ≤ pageSize
{
"id": "u_001", // 字符串,非空
"name": "张三", // 字符串,非空
"age": 28, // 数字,0-150
"email": "zhangsan@example.com" // 字符串,符合邮箱格式
}
]
}
}
3.5 接口校验的 Testing 断言模式
在 Go 的 testing 包中,接口校验通常封装为以下模式:
// 通用 HTTP 响应校验函数
func assertResponse(t *testing.T, resp *http.Response, expectedStatus int) {
t.Helper()
if resp.StatusCode != expectedStatus {
t.Errorf("期望状态码 %d,实际 %d", expectedStatus, resp.StatusCode)
}
// 确保响应体可读
body, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatalf("读取响应体失败: %v", err)
}
// 解析 JSON
var result map[string]interface{}
if err := json.Unmarshal(body, &result); err != nil {
t.Fatalf("JSON 解析失败: %v", err)
}
// 校验业务状态码
if code, ok := result["code"].(float64); ok {
if int(code) != 200 {
t.Errorf("业务状态码异常: %v", code)
}
}
}
压测集成建议: 在压测脚本(如 k6)中,使用
check() 函数同时校验状态码、响应时间和 JSON 字段。例如:check(res, { 'status is 200': (r) => r.status === 200, 'body has id': (r) => r.json().id !== undefined })。
3.6 本章小结
- HTTP 请求方法决定操作语义,压测用例必须匹配接口设计(GET 查、POST 建、PUT 改、DELETE 删)。
- 状态码是接口校验的第一道防线:2xx 成功、4xx 客户端错误、5xx 服务端错误。
- 请求头携带认证、格式、幂等等元信息,压测中需动态生成或管理。
- 响应体校验需覆盖字段存在性、类型、值范围与嵌套结构,避免只校验状态码。
- Testing 驱动压测的核心:将 HTTP 协议知识转化为可重复执行的断言逻辑。