fetch 如何处理 302?
作者:时倾
来源:SegmentFault 思否社区
问题描述
fetch 发送一个请求,请求登录过期返回 302,浏览器自动重定向到 Response Headers 的 Location 登录页面。Location 对应的服务器不接受跨域请求,因此页面报错。
尝试在 fetch 的回调函数处理,一旦 fetch 的 response status 是 302 就跳转到 Location 页面, 但是不论在fetch的回调函数中做任何事情,都执行不到。
什么是 HTTP 状态码 302 ?
HTTP 302 重定向状态码表明请求的资源被暂时的移动到了由Location头部指定的 URL 上。浏览器会重定向到这个URL, 但是搜索引擎不会对该资源的链接进行更新。
使用场景:
在 OAuth 流程中,302 经常使用;
有时候请求的资源无法从其标准地址访问,但是却可以从另外的地方访问。在这种情况下可以使用临时重定向。
搜索引擎不会记录该新的、临时的链接。在创建、更新或者删除资源的时候,临时重定向也可以用于显示临时性的进度页面。
fetch 为什么不能拦截302?
fetch 发送请求;
服务器返回 response 并且带有状态码(比如200) ;
浏览器接收到响应,结果递交给fetch;
从 fetch 的回调函数获取相应数据;
fetch 发送请求;
服务器返回 response (带有location) 并且带有 302 状态码;
浏览器接收到响应,自动从302响应的头信息的重定向地址中取到 location 进行跳转;
如何解决?
1. 配置 fetch 的 redirect
follow:默认, 自动重定向;
error:如果产生重定向将自动终止并且抛出一个错误;
manual:手动处理重定向;
error
fetch 只有服务器错误才调用 catch,其他都会调用 then 函数,那么 302 为什么会调用catch? 不是 302 导致 catch 被调用而是重定向后的请求的 response 导致 catch 被调用。
manual
2. 后端改写状态码,前端手动处理
301 和 302 状态码区别
之后每次请求都会跳转到 location 对应的url。没有例外。
浏览器可以缓存从这个 url 获取的响应。
每次请求不能确定是否向 Location 的 url 发请求,因此需要先想原来的 url 发送请求确定。
浏览器不可缓存从重定向的 url 获取到的响应。
重定向可以用来set cookie
用户访问 a 域名
后端返回302,location是 b 域名,同时set-cookie: cookieA
浏览器在 a 域名下种上cookie: cookieA,然后向 b 域名发起请求
后端返回 302,location 是a 域名,同时 set-cookie: cookieB
浏览器在 b 域名下种上cookie: cookieB,然后向 a 域名发起请求
其实跨域 set cookie 还可以用浏览器的 beacon API 实现,当然也是有一些限制的 重定向可以有多次,比如连续的302, 就是 location 对应的 URL 又返回了 302 和新的location,如此重复直到不再跳转位置。为了防止出现无限重定向的情况,重定向的次数是有上限的。Chrome 浏览器的重定向次数是20,超过20次重定向就会报ERR_TOO_MANY_REDIRECT错误。