02 HTTP协议详解 - 接口测试的基石
🎯 本章目标:深入理解HTTP/HTTPS协议,掌握请求方法、状态码、请求头/响应头,为接口测试打下坚实基础。
2.1 HTTP是什么?
生活中的类比
想象HTTP协议就像寄快递的标准流程:
你(寄件人) 快递公司(HTTP协议) 收件人(服务器)
│ │ │
│ 1. 填写快递单(请求) │ 2. 按标准运输 │
│ ──────────────────────> │ ──────────────────────> │
│ │ │
│ 4. 收到回执(响应) │ 3. 按标准返回 │
│ <────────────────────── │ <────────────────────── │
HTTP(HyperText Transfer Protocol,超文本传输协议) 是客户端和服务器之间通信的标准协议。
HTTP的工作方式
关键特点:
- 无状态:每次请求都是独立的,服务器不记住之前的请求
- 请求-响应模式:客户端发起请求,服务器返回响应
- 基于TCP:HTTP建立在TCP协议之上
2.2 HTTP vs HTTPS
对比表
| 特性 | HTTP | HTTPS |
|---|---|---|
| 全称 | HyperText Transfer Protocol | HyperText Transfer Protocol Secure |
| 安全性 | 明文传输,不安全 | 加密传输,安全 |
| 端口 | 80 | 443 |
| 加密方式 | 无 | SSL/TLS加密 |
| 性能 | 较快 | 稍慢(有加密开销) |
| SEO | 搜索引擎降权 | 搜索引擎优先收录 |
| 证书 | 不需要 | 需要SSL证书 |
简单理解:
- HTTP = 寄明信片,邮递员可以看到内容
- HTTPS = 寄密码信,只有收件人能打开
2.3 HTTP请求详解
请求结构
POST /api/login HTTP/1.1 ← 请求行(方法 + URL + 协议版本)
Host: api.example.com ←
Content-Type: application/json ← 请求头(Request Headers)
Authorization: Bearer xxx ←
Content-Length: 56 ←
← 空行(分隔符)
{"username":"admin","password":"123456"} ← 请求体(Request Body)
请求方法(HTTP Methods)
| 方法 | 用途 | 是否幂等 | 是否安全 | 参数位置 | 示例 |
|---|---|---|---|---|---|
| GET | 获取资源 | 是 | 是 | URL(Query) | GET /users?id=1 |
| POST | 创建资源 | 否 | 否 | Body | POST /users |
| PUT | 全量更新 | 是 | 否 | Body | PUT /users/1 |
| PATCH | 部分更新 | 否 | 否 | Body | PATCH /users/1 |
| DELETE | 删除资源 | 是 | 否 | URL | DELETE /users/1 |
幂等性 :多次执行结果相同。比如GET /users/1 执行100次,结果都一样。
安全性:不会改变服务器状态。GET是安全的,POST/PUT/DELETE不安全。
生动例子
把HTTP方法比作餐厅点餐:
GET → 看菜单(获取信息,不改变什么)
POST → 点新菜(创建新订单)
PUT → 修改整单(把订单全部换成别的菜)
PATCH → 修改部分(只把可乐换成雪碧)
DELETE → 取消订单(删除)
2.4 HTTP响应详解
响应结构
HTTP/1.1 200 OK ← 状态行(协议 + 状态码 + 状态描述)
Content-Type: application/json ←
Content-Length: 123 ← 响应头(Response Headers)
Server: nginx/1.18.0 ←
Date: Mon, 01 Jan 2024 00:00:00 GMT ←
← 空行
{"code":0,"data":{"name":"张三"}} ← 响应体(Response Body)
HTTP状态码
状态码是服务器对请求的"回答",分为5大类:
常见状态码详解
| 状态码 | 含义 | 场景 | 测试关注点 |
|---|---|---|---|
| 200 | OK | 请求成功 | 验证返回数据正确性 |
| 201 | Created | 创建成功 | 验证资源是否创建 |
| 204 | No Content | 删除成功 | 验证资源是否删除 |
| 301 | 永久重定向 | URL已变更 | 验证跳转是否正确 |
| 302 | 临时重定向 | 临时跳转 | 验证跳转是否正确 |
| 400 | 请求参数错误 | 参数缺失/格式错误 | 验证参数校验 |
| 401 | 未认证 | 未登录/Token失效 | 验证认证机制 |
| 403 | 无权限 | 权限不足 | 验证授权机制 |
| 404 | 资源不存在 | URL错误或资源已删除 | 验证错误处理 |
| 422 | 语义错误 | 参数格式对但逻辑错 | 验证业务校验 |
| 500 | 服务器内部错误 | 代码异常 | 验证异常处理 |
| 502 | 网关错误 | 上游服务故障 | 验证容错机制 |
| 503 | 服务不可用 | 服务维护/过载 | 验证降级策略 |
状态码记忆口诀
1xx: Hold on(等一下)
2xx: Here you go(给你)
3xx: Go away(去别的地方)
4xx: You messed up(你错了)
5xx: I messed up(我错了)
2.5 HTTP请求头(Request Headers)
请求头是客户端告诉服务器"我是谁"、"我要什么"的信息。
常见请求头
| 请求头 | 说明 | 示例 |
|---|---|---|
| Host | 目标服务器域名 | Host: api.example.com |
| Content-Type | 请求体格式 | Content-Type: application/json |
| Accept | 期望的响应格式 | Accept: application/json |
| Authorization | 认证信息 | Authorization: Bearer token123 |
| User-Agent | 客户端信息 | User-Agent: Mozilla/5.0... |
| Cookie | 携带的Cookie | Cookie: sessionId=abc123 |
| Content-Length | 请求体长度 | Content-Length: 56 |
Content-Type 详解
| Content-Type | 用途 | 示例 |
|---|---|---|
application/json |
传递JSON数据 | {"name":"张三"} |
application/x-www-form-urlencoded |
表单提交 | name=张三&age=20 |
multipart/form-data |
文件上传 | 带boundary的分隔数据 |
text/xml |
XML数据 | <user><name>张三</name></user> |
text/plain |
纯文本 | Hello World |
2.6 HTTP响应头(Response Headers)
响应头是服务器告诉客户端"我是什么"、"怎么处理响应"的信息。
常见响应头
| 响应头 | 说明 | 示例 |
|---|---|---|
| Content-Type | 响应体格式 | Content-Type: application/json |
| Content-Length | 响应体长度 | Content-Length: 1234 |
| Set-Cookie | 设置Cookie | Set-Cookie: sessionId=abc; Path=/ |
| Cache-Control | 缓存策略 | Cache-Control: no-cache |
| Location | 重定向地址 | Location: https://new-url.com |
| Server | 服务器信息 | Server: nginx/1.18.0 |
| Date | 响应时间 | Date: Mon, 01 Jan 2024 00:00:00 GMT |
2.7 完整的HTTP请求-响应示例
场景:用户登录
请求:
http
POST /api/login HTTP/1.1
Host: www.example.com
Content-Type: application/json
User-Agent: Mozilla/5.0
Content-Length: 45
{"username":"admin","password":"123456"}
响应(成功):
http
HTTP/1.1 200 OK
Content-Type: application/json
Set-Cookie: sessionId=abc123; Path=/; HttpOnly
Content-Length: 56
{
"code": 0,
"message": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"expires": 3600
}
}
响应(失败-密码错误):
http
HTTP/1.1 401 Unauthorized
Content-Type: application/json
Content-Length: 48
{
"code": 1001,
"message": "用户名或密码错误"
}
2.8 Cookie、Session、Token
三者对比
| 特性 | Cookie | Session | Token(JWT) |
|---|---|---|---|
| 存储位置 | 浏览器 | 服务器 | 客户端(浏览器/内存) |
| 安全性 | 低(可被篡改) | 中 | 高(签名验证) |
| 服务器压力 | 小 | 大(存储Session) | 小(无状态) |
| 跨域支持 | 受限 | 受限 | 支持 |
| 适用场景 | 简单网站 | 传统Web应用 | 现代API、微服务 |
JWT Token详解
JWT结构 :Header.Payload.Signature
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjEsIm5hbWUiOiJhZG1pbiJ9.SflKxwRJSMeKKF2QT4fwpMe...
↑Header(Base64) ↑Payload(Base64) ↑Signature(签名)
2.9 HTTP/1.1 vs HTTP/2 vs HTTP/3
| 特性 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| 发布年份 | 1997 | 2015 | 2022 |
| 传输层 | TCP | TCP | QUIC (基于UDP) |
| 连接复用 | 需多个TCP连接 | 单一TCP连接多路复用 | 多路复用 |
| 头部压缩 | 无 | HPACK | QPACK |
| 服务器推送 | 无 | 支持 | 支持 |
| 队头阻塞 | 有 | TCP层有 | 无 |
2.10 本章实战:用浏览器开发者工具观察HTTP
步骤
- 打开Chrome浏览器,按 F12 打开开发者工具
- 切换到 Network(网络)标签
- 访问任意网站(如 https://jsonplaceholder.typicode.com)
- 观察请求列表
观察要点
点击某个请求,查看:
- Headers:请求头和响应头
- Payload:请求参数
- Preview/Response:响应数据
- Timing:请求各阶段耗时
2.11 本章小结
核心知识点
- 请求结构:请求行(方法 + URL + 版本)、请求头(元信息)、请求体(传输数据)
- 响应结构:状态行(版本 + 状态码 + 描述)、响应头(元信息)、响应体(返回数据)
- 请求方法:GET/POST/PUT/PATCH/DELETE,幂等性概念
- 状态码:2xx成功 3xx重定向 4xx客户端错 5xx服务端错
- 认证方式:Cookie/Session/Token,JWT原理
必须记住的状态码
| 类别 | 必记状态码 |
|---|---|
| 2xx | 200, 201, 204 |
| 3xx | 301, 302, 304 |
| 4xx | 400, 401, 403, 404, 422 |
| 5xx | 500, 502, 503 |
课后练习 📝
- 实践题:用浏览器F12访问一个网站,找到一个API请求,分析它的请求方法、请求头、响应状态码和响应数据。
- 思考题:为什么POST请求不是幂等的?什么场景下需要幂等性设计?
- 对比题:比较Cookie、Session、Token三种认证方式的优缺点,什么场景适合用什么?
- 场景题:设计一个用户注册接口,应该用什么HTTP方法?可能的返回状态码有哪些?
2.12 下章预告
下一章我们将学习RESTful API设计规范,理解如何设计优雅的接口,以及如何测试RESTful接口!
"HTTP协议是接口测试的基石,掌握它,你就掌握了与服务器对话的语言。"