第2章:HTTP协议核心——请求方法、状态码、头信息与状态管理

做接口测试,说白了就是在跟 HTTP 协议打交道。你发的每一个请求,收的每一个响应,底层都是协议在说话。我刚开始接触接口时,总觉得协议是理论课的东西,直到有一次线上事故——某个同事把 GET 请求硬改成 POST,结果缓存层全挂了,用户数据刷不出来。嗯,从那时起我才真正意识到:协议规则不是摆设,它是接口系统的骨架。

2.1 请求方法:你用什么方式跟服务器说话

HTTP 定义了一组“动词”,告诉服务器你想干什么。最常用的就四个:GET、POST、PUT、DELETE。我把它们的核心区别整理成一张表,方便你对照。

方法 语义 请求体 幂等性 常见用途
GET 查询资源 无 是 获取列表、详情
POST 创建资源 有 否 新增订单、提交表单
PUT 全量更新资源 有 是 修改用户信息
DELETE 删除资源 可有可无 是 删除记录

关键原则:GET 请求不能带请求体,也不应该有副作用。我见过有人把大批量查询参数塞进 GET 的 URL 里,结果 URL 超长被网关截断——接口直接返回 414。用 POST 才能放心传大量数据。

2.2 状态码:服务器在告诉你什么

状态码是服务器给你的一张“脸色”。我把它分成五个区间,每个区间一个意思。你测试时只要记住:2xx 正常,4xx 你错了,5xx 服务器炸了。

  • 2xx 成功
    • 200 OK — 正常返回
    • 201 Created — 创建成功(POST 常用)
    • 204 No Content — 删除成功,响应体为空
  • 3xx 重定向
    • 301 / 302 — 资源迁移,接口测试中很少直接处理,但要注意测试用例里不要被跳转迷惑
  • 4xx 客户端错误
    • 400 Bad Request — 参数格式错误
    • 401 Unauthorized — 没登录
    • 403 Forbidden — 权限不够
    • 404 Not Found — 接口地址写错了
    • 405 Method Not Allowed — 方法不支持(比如接口只接受 POST,你用 GET 就返这个)
    • 429 Too Many Requests — 限流了
  • 5xx 服务端错误
    • 500 Internal Server Error — 代码抛异常了
    • 502 Bad Gateway — 网关或反向代理挂了
    • 503 Service Unavailable — 服务过载或维护中

我曾经踩过的坑:某个接口在异常时返回了 200,但响应体里塞了一个 errorCode 告诉调用方失败了。测试脚本没检查 body 里的错误码,结果认为所有 200 都是成功的——线上出了严重误报。记住:状态码只代表协议层面的成功,不代表业务成功。测试断言必须同时检查状态码和业务字段。

2.3 请求头与响应头:藏在信封里的元信息

HTTP 头和信封上的收件人地址、邮戳一样,告诉双方怎么处理这封信。你在测试中最常打交道的头我列在下面:

头字段 方向 说明 测试关注点
Content-Type 请求/响应 告诉对方数据格式,比如 application/json 如果设了 JSON 但 body 格式不对,会返回 415
Authorization 请求 携带令牌(Bearer / Basic Auth) 缺失或过期 → 401
Accept 请求 客户端期望的响应格式 匹配不对可能返回 406
Set-Cookie 响应 服务端下发 Cookie 需要后续请求自动带上
Cache-Control 响应 控制缓存策略 测试接口是否被错误缓存
Location 响应 重定向目标地址(配合 3xx) 确认跳转路径正确

我建议你用抓包工具(比如 Charles 或浏览器的 DevTools)观察一次完整的登录流程。看看请求先发 POST /login,服务端返回 Set-Cookie,然后后续请求在 Cookie 头里带着它——这样你才能真正理解“无状态协议”是怎么通过头信息实现有状态的。

2.4 Cookie 与 Session:让无状态协议记住你是谁

HTTP 本身是无状态的——每个请求都是独立的孤儿。但业务需要“登录后不要每次都输密码”。于是有了 Cookie 和 Session 这对搭档。

Cookie 的工作流:

  1. 客户端 POST 用户名密码给登录接口
  2. 服务端验证通过,生成一个 Session ID,存在内存或 Redis 里
  3. 服务端在响应头加 Set-Cookie: sessionid=abc123
  4. 浏览器自动保存这个 Cookie,后续请求自动带上 Cookie: sessionid=abc123
  5. 服务端根据 sessionid 查 Session 数据,知道你是哪个用户

个人小习惯:在接口测试脚本里,我会用一个全局的 cookies_dict 来维护登录后的 Cookie。每次发送请求前,用 session.cookies.update() 把响应的 Set-Cookie 同步进去。千万不要手动拼接 Cookie 字符串,容易漏掉 Domain、Path 属性。

import requests

session = requests.Session()
# 登录
resp = session.post('https://api.example.com/login', json={'user':'admin','pass':'123'})
# session 对象自动处理了 Set-Cookie,后续请求直接用
resp2 = session.get('https://api.example.com/profile')
print(resp2.json())

用 Session 对象是你最稳妥的做法。它会自动跟踪 Cookie,也支持手动设置 headers。你想想看,如果每个接口都要你自己从响应里抠出 Cookie 再塞进下一个请求,不仅麻烦还容易出 bug。

注意事项:Cookie 有 HttpOnly 和 Secure 标志。HttpOnly 的 Cookie 无法被 JavaScript 读取,能防 XSS 攻击。你在做 Web 端测试时,如果发现 JS 读不到 Cookie,别慌,那是安全设计。另外 Secure 标志要求 Cookie 只在 HTTPS 下传输,测试环境如果走 HTTP 会发送失败。

2.5 本章知识体系一图揽

HTTP 核心知识体系 请求方法 GET / POST PUT / DELETE 状态码 2xx 成功 4xx 客户端错 / 5xx 服务端错 请求头 & 响应头 Content-Type Authorization / Set-Cookie 状态管理 Cookie Session 接口测试核心关注点 方法验证 确认方法是否允许 幂等性测试 状态码断言 预期 vs 实际状态码 业务码双重校验 头与 Cookie 管理 自动携带 Cookie Session 一致性 工具:Postman / requests 抓包验证:DevTools / Charles 自动化:pytest + requests.Session 掌握这四块,接口测试底层逻辑就通了

好了,这张图把本章四个核心知识块串起来了。你写测试用例时,记住从 方法语义 → 状态码预期 → 头信息验证 → 会话保持 这四个维度去设计,覆盖率就基本到位了。

我个人建议你每次接到新接口,先拿 Postman 手工调通一遍,确认方法和头都正确,再写自动化。不要一上来就写代码,那样很容易被协议细节绊倒。