当接口请求遇到 302 状态码……

大家好,我是刘布斯。

前两天在面试一位同学的时候,聊到了 token 过期,需要重新登录的场景。

这位同学提到,当时后端对过期的 token 进行了拦截,接口会返回 302 状态码,前端就会进行重定向到登录页面。

我提出了质疑:接口返回302,浏览器会自动做重定向到登录页吗?

这位同学顿时愣住了,但短暂的思考后,坚定地回复:我们对网络请求做了封装,当监测到 302 的状态码,就会用 js 做重定向。

这位同学的回答确实有问题,今天我们就来聊聊,当接口请求遇到 302 的时候会发生什么。

302/303/307 状态码

状态码是常见的面试题,以 3xx 开头的常见状态码有:

  • 301:永久重定向。请求资源的 URL 已永久更改。在响应中给出了新的 URL。
  • 302:临时重定向。此响应代码表示所请求资源的 URI 已 暂时 更改。未来可能会对 URI 进行进一步的改变。因此,客户机应该在将来的请求中使用这个相同的 URI。
  • 303:临时重定向。重定向的方法会统一使用 GET 。
  • 304:内容未改变。用于浏览器的缓存,告诉客户端响应还没有被修改,因此客户端可以继续使用相同的缓存版本的响应。
  • 307 :也是临时重定向。与 302 有相同的语义,但用户代理不能更改所使用的 HTTP 方法:如果在第一个请求中使用了 POST,则在重定向的请求中也必须使用 POST

重定向,顾名思义,就是把请求重新指向了一个新的地址。

上面可以看到 302/303/307 这三个状态码的功能比较类似,将它们单独拎出来对比下差异:

状态码 状态文本 处理方法 典型应用场景
302 Found GET 方法不会发生变更。其他方法有可能会变更为 GET 方法。 由于不可预见的原因该页面暂不可用。
303 See Other GET 方法不会发生变更,其他方法会变更为 GET 方法(消息主体丢失)。 用于 PUT 或 POST 请求完成之后重定向,来防止由于页面刷新导致的操作的重复触发。
307 Temporary Redirect 方法和消息主体都不发生变化。 由于不可预见的原因该页面暂不可用。当站点支持非 GET 方法的链接或操作的时候,该状态码优于 302 状态码。

手动处理接口的重定向?

302 状态码有个问题:浏览器通常会自动发起对重定向地址的请求,js 无法插手干预

对于重定向,当浏览器检查到 headers 中存在 Location,会直接进行跳转,不会告知任何请求发送者(fetch),这时候发送者会以为请求还在处理中。所以此时的 fetch 的 then 和catch 都捕获不到信息

在使用 fetch 进行请求的时候,可以通过 redirect 参数配置如何处理重定向。

redirect可选的值有三个:

  • follow:自动重定向
  • error :如果产生重定向将自动终止并且抛出一个错误TypeError: Failed to fetch
  • manual:手动处理重定向

在 Chrome 中默认使用follow(Chrome 47之前的默认值是manual)。

大家是不是以为,我们可以设置成 manual 后,拿到 3xx 的状态码和重定向的地址,我们可以在 js 中自定义实现自定义的跳转?

其实并不是,manual 的准确意思并不是手动处理,而是让浏览器不做处理。通过这种方法只能知道发生了重定向,但是 response 的内容非常有限,无法获取到具体的信息(可以参考这个 issue:Cannot get next URL for redirect="manual")。

具体一点,如果我们设置成 manual时,如果发生了重定向,会拿到 typeopaqueredirect 的response:

json 复制代码
{
    "body": null,
    "bodyUsed": false,
    "headers": {},
    "ok": false,
    "redirected": false,
    "status": 0,
    "statusText": "",
    "type": "opaqueredirect",
    "url": "https://xxx.com",
}

另外提一句,manual 一般是配合 Service Worker 使用。

302 状态码的总结

当浏览器发起一个请求,服务端返回了302状态码,浏览器会根据响应头中的 location 字段,重新发起一个请求。当重定向次数过多的时候,浏览器会抛出 ERR_TOO_MANY_REDIRECT 的异常。

请求分两种情况:

  • 浏览器页面请求:跳转到新的页面。
  • ajax请求:返回最后重定向地址的响应。

面试的那位同学提到,服务端会在接口中返回302,然后由前端进行拦截,大概率是记错了。

如何处理未登录跳转的问题

那么问题来了,我们该如何处理未登录的问题呢?

比较常规的方案是后端返回 401 状态码,前端对接口请求进行封装,遇到 401 状态码就跳转到登录页面。

最后

还没有使用过我们刷题网站(fe.ecool.fun/)或者刷题小程序(前端面试题宝典)的同学,如果近期准备或者正在找工作,千万不要错过,题库主打无广告和更新快哦~。

相关推荐
栈老师不回家1 小时前
Vue 计算属性和监听器
前端·javascript·vue.js
前端啊龙1 小时前
用vue3封装丶高仿element-plus里面的日期联级选择器,日期选择器
前端·javascript·vue.js
一颗松鼠1 小时前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
小远yyds1 小时前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
吕彬-前端2 小时前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱2 小时前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai2 小时前
uniapp
前端·javascript·vue.js·uni-app
帅比九日3 小时前
【HarmonyOS Next】封装一个网络请求模块
前端·harmonyos
bysking3 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓4 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js