大家好,我是刘布斯。
前两天在面试一位同学的时候,聊到了 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
时,如果发生了重定向,会拿到 type
为 opaqueredirect
的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/)或者刷题小程序(前端面试题宝典)的同学,如果近期准备或者正在找工作,千万不要错过,题库主打无广告和更新快哦~。