请求接口302 Moved Temporarily
这是一个非常常见的 HTTP 状态码。我来为您详细解释 302 Found
(通常被称为 302 Moved Temporarily
) 的含义、原因以及作为前端开发者该如何处理。
1. 核心含义
302 Moved Temporarily 是一个 HTTP 重定向 状态码。它意味着:
你请求的资源暂时位于另一个不同的 URL 下。客户端(浏览器或 Axios)应该使用原始的请求方法(如 GET、POST)自动地向这个新的 URL 再次发起请求,但你以后还是应该继续使用原来的 URL。
关键词:暂时、自动重定向、保持原方法。
2. 工作流程
当你使用 Axios 请求接口 A,服务器返回 302 时,整个过程如下:
3. 常见触发场景
服务器返回 302 通常是出于以下目的:
-
用户登录状态验证(最常见):
- 场景:你请求一个需要登录的接口(如
/api/user/profile
),但你的 token 已过期或无效。 - 服务器行为:服务器不返回 401(未授权),而是返回 302,将你重定向到登录页面(如
/login.html
)。 - 问题:前端期望拿到 JSON 数据,却拿到了一个 HTML 页面,导致解析错误。
- 场景:你请求一个需要登录的接口(如
-
接口路径变更或灰度发布:
- 后端接口的路径暂时调整了,但为了兼容老客户端,用 302 将请求转发到新路径。
-
负载均衡:
- 将请求临时重定向到另一台服务器实例以分摊流量。
-
简化 URL:
- 访问
https://example.com/about
时,服务器可能重定向到https://example.com/about/index.html
。
- 访问
4. 前端如何应对和处理(以 Axios 为例)
Axios 默认会自动处理 3xx 重定向状态码(包括 302)。这意味着你通常感知不到302 的发生,Axios 会帮你完成重定向请求,你最终拿到的是重定向后最后一个请求的响应。
你需要关注的是以下两种情况:
情况一:不希望自动重定向,想自己处理
你可以配置 Axios 让它不自动重定向,这样你就能捕获到 302 响应并自行处理。
import axios from 'axios';// 创建一个自定义的 Axios 实例
const instance = axios.create({// 设置 maxRedirects 为 0 来禁止自动重定向maxRedirects: 0,// 或者使用 validateStatus 自定义哪些状态码不抛出错误validateStatus: function (status) {return status >= 200 && status < 303; // 允许 200-302,Axios 仍会处理 302 为重定向},
});// 发送请求
instance.get('/api/need-auth').then(response => {// 如果请求成功且没有重定向,会进入这里console.log('成功数据:', response.data);}).catch(error => {// 如果禁止了重定向,服务器返回 302 会进入 catchif (error.response && error.response.status === 302) {const redirectUrl = error.response.headers.location; // 获取重定向目标URLconsole.warn('请求被重定向至:', redirectUrl);// 自定义处理逻辑,例如:// 1. 跳转到登录页if (redirectUrl.includes('/login')) {window.location.href = redirectUrl; // 用浏览器全局跳转}// 2. 或用新的 URL 重新请求// return instance.get(redirectUrl);} else {console.error('其他错误:', error);}});
情况二:自动重定向后,后端返回了非 JSON 数据(如 HTML)
这是最常见的问题。当你请求一个 API,但因为它重定向到了登录页面,Axios 最终拿到了 HTML,解析 JSON 时就会报错 SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
。
解决方案:在拦截器中统一处理
import axios from 'axios';const instance = axios.create();// 添加响应拦截器
instance.interceptors.response.use((response) => {// 2xx 范围内的状态码都会触发该函数。return response;},(error) => {// 超出 2xx 范围的状态码都会触发该函数。const { response } = error;if (response) {// 检查响应头,如果返回的是 HTML,很可能是重定向到了登录页const contentType = response.headers['content-type'];if (response.status >= 300 && response.status < 400) {// 虽然状态码是3xx,但如果你配置了maxRedirects:0,会进入这里console.log('重定向发生');} else if (contentType && contentType.includes('text/html')) {// 最重要的一点:期望收到JSON,却收到了HTMLconsole.error('收到HTML响应,接口可能已重定向至登录页');// 执行全局登出逻辑store.dispatch('user/logout'); // 清除Vuex/Pinia中的用户状态localStorage.removeItem('token'); // 清除tokenrouter.push('/login'); // 跳转到登录页// 也可以直接使用 window.location.href 进行硬刷新跳转}}return Promise.reject(error);}
);export default instance;
5. 302 与 301(Moved Permanently)的区别
特性 | 302 Found (Temporary) | 301 Moved Permanently |
---|---|---|
性质 | 临时重定向 | 永久重定向 |
SEO 影响 | 搜索引擎会保留原始 URL,索引原地址 | 搜索引擎会将权重转移到新 URL,索引新地址 |
浏览器行为 | 下次请求可能还会访问原地址 | 浏览器可能会缓存重定向结果,下次直接访问新地址 |
应用场景 | 临时维护、登录跳转、A/B 测试 | 网站重构、域名永久更换 |
总结
- 302 是什么? 是一个临时重定向信号。
- 谁在处理它? Axios 和浏览器默认会自动处理,对你来说是透明的。
- 最常见的问题? 接口因未登录被重定向到登录页面,导致前端拿到 HTML 而非 JSON,引发解析错误。
- 如何解决? 在 Axios 的响应拦截器中检查响应内容类型(
Content-Type
),如果是text/html
但你又期望application/json
,则很可能是身份验证失效,应执行清除 Token 和跳转登录页的逻辑。