[L1] HTTP 常见状态码含义与 301 和 302 的区别
一句话结论
HTTP 状态码分五类,301 永久重定向会被浏览器/爬虫缓存,302 临时重定向每次请求仍询问服务器。
体系讲解
1. 五类状态码速查
| 类别 | 范围 | 含义 | 常见码 |
|---|---|---|---|
| 1xx | 100–199 | 信息性,请求已收到,继续处理 | 100 Continue |
| 2xx | 200–299 | 成功 | 200 OK、201 Created、204 No Content |
| 3xx | 300–399 | 重定向,需进一步操作 | 301、302、304 Not Modified |
| 4xx | 400–499 | 客户端错误 | 400 Bad Request、401、403、404、422 |
| 5xx | 500–599 | 服务端错误 | 500 Internal Server Error、502、503、504 |
2. 高频状态码逐一说明
| 状态码 | 含义 | PHP 场景 |
|---|---|---|
| 200 | 请求成功,响应体含数据 | 正常接口返回 |
| 201 | 资源创建成功 | POST 新增资源后返回 |
| 204 | 成功但无响应体 | DELETE 操作 |
| 301 | 永久重定向,新 URL 被缓存 | HTTP → HTTPS 迁移、域名更换 |
| 302 | 临时重定向,不缓存 | 登录后跳转、A/B 测试 |
| 304 | 资源未修改,使用本地缓存 | 协商缓存命中 |
| 400 | 请求参数错误 | 表单校验失败 |
| 401 | 未认证(需登录) | JWT 过期 |
| 403 | 已认证但无权限 | 越权访问 |
| 404 | 资源不存在 | 路由匹配失败 |
| 500 | 服务端未捕获异常 | PHP Fatal Error |
| 502 | 网关收到上游无效响应 | PHP-FPM 崩溃 |
| 503 | 服务不可用(过载/维护) | 限流后降级 |
3. 301 vs 302 核心差异
| 维度 | 301 永久重定向 | 302 临时重定向 |
|---|---|---|
| 浏览器缓存 | ✅ 缓存新 URL,后续直接访问新地址 | ❌ 不缓存,每次都请求原 URL |
| 搜索引擎(SEO) | 权重转移到新 URL | 权重保留在原 URL |
| 适用场景 | 域名永久迁移、HTTP → HTTPS | 登录跳转、临时活动页、A/B 测试 |
| PHP 实现 | header("Location: ...", true, 301) | header("Location: ...") 默认 302 |
4. PHP 发送重定向
header() 函数必须在任何输出(包括空格)之前调用,否则报 headers already sent 错误。Location 响应头告知客户端跳转目标,浏览器收到后自动发起新请求。
考察意图
考察候选人对 HTTP 协议基础的掌握程度:能否快速定位常见状态码的语义、理解 301/302 对浏览器缓存和 SEO 的不同影响,以及在 PHP 中正确使用 header() 发送重定向。
追问链
401 和 403 有什么区别?
401 表示未认证(请求方身份未知,需先登录/提供凭证);403 表示已认证但无权限(知道你是谁,但你没有访问该资源的权限)。常见误用:把「未登录」返回 403 而非 401。302 重定向后,原请求的 HTTP 方法会改变吗?
大多数浏览器在 302 重定向后会将 POST 改为 GET(历史行为),导致表单数据丢失。若需保留请求方法,应使用 307(临时)或 308(永久)重定向。PHP 的
header("Location: ...")之后还需要exit吗?
需要。header()只是设置响应头,PHP 脚本会继续执行。不加exit/die,后续代码仍会运行(可能输出额外内容或执行危险逻辑),应立即终止脚本。304 和 200 的区别是什么?
200 返回完整响应体;304 表示资源自上次请求以来未修改,响应体为空,客户端直接使用本地缓存副本(需配合ETag或Last-Modified等协商缓存头实现)。
易错点
混淆 401 与 403:「未登录」应返回 401,「已登录但无权限」才返回 403。很多系统将两者统一返回 403,导致客户端无法区分是需要登录还是权限不足。
301 缓存不可逆的副作用:301 被浏览器永久缓存后,若需撤销重定向,用户必须手动清除浏览器缓存才能访问原 URL,测试/开发阶段应用 302 代替。
header()后忘加exit:发送Location头后未终止脚本,后续代码继续执行,轻则多余计算,重则绕过权限检查(攻击者用 Burp Suite 等工具拦截响应可忽略 302 继续访问)。
代码示例
// 永久重定向(HTTP → HTTPS 迁移)
if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') {
header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], true, 301);
exit;
}
// 临时重定向(登录检查)
if (!isLoggedIn()) {
header('Location: /login', true, 302); // 302 可省略,为默认值
exit;
}
// 保留请求方法的临时重定向(表单 POST → POST)
header('Location: /new-endpoint', true, 307);
exit;