Skip to content

[L1] HTTP 常见状态码含义与 301 和 302 的区别

一句话结论

HTTP 状态码分五类,301 永久重定向会被浏览器/爬虫缓存,302 临时重定向每次请求仍询问服务器。

体系讲解

1. 五类状态码速查

类别范围含义常见码
1xx100–199信息性,请求已收到,继续处理100 Continue
2xx200–299成功200 OK、201 Created、204 No Content
3xx300–399重定向,需进一步操作301、302、304 Not Modified
4xx400–499客户端错误400 Bad Request、401、403、404、422
5xx500–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() 发送重定向。

追问链

  1. 401 和 403 有什么区别?
    401 表示未认证(请求方身份未知,需先登录/提供凭证);403 表示已认证但无权限(知道你是谁,但你没有访问该资源的权限)。常见误用:把「未登录」返回 403 而非 401。

  2. 302 重定向后,原请求的 HTTP 方法会改变吗?
    大多数浏览器在 302 重定向后会将 POST 改为 GET(历史行为),导致表单数据丢失。若需保留请求方法,应使用 307(临时)或 308(永久)重定向。

  3. PHP 的 header("Location: ...") 之后还需要 exit 吗?
    需要。header() 只是设置响应头,PHP 脚本会继续执行。不加 exit/die,后续代码仍会运行(可能输出额外内容或执行危险逻辑),应立即终止脚本。

  4. 304 和 200 的区别是什么?
    200 返回完整响应体;304 表示资源自上次请求以来未修改,响应体为空,客户端直接使用本地缓存副本(需配合 ETagLast-Modified 等协商缓存头实现)。

易错点

  1. 混淆 401 与 403:「未登录」应返回 401,「已登录但无权限」才返回 403。很多系统将两者统一返回 403,导致客户端无法区分是需要登录还是权限不足。

  2. 301 缓存不可逆的副作用:301 被浏览器永久缓存后,若需撤销重定向,用户必须手动清除浏览器缓存才能访问原 URL,测试/开发阶段应用 302 代替。

  3. header() 后忘加 exit:发送 Location 头后未终止脚本,后续代码继续执行,轻则多余计算,重则绕过权限检查(攻击者用 Burp Suite 等工具拦截响应可忽略 302 继续访问)。

代码示例

php
// 永久重定向(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;

基于 Apache License 2.0 开源