背景: 根据业务场景需要拦截302做后续的逻辑处理
尝试一: : axios拦截
、、、、、 async created() { // 获取302请求返回的location后手动修改video的src路径 let targetSrc; try { await axios.get(this.video).then((res) => { const { headers, status } = res; const { location } = headers; if(status === 302) { targetSrc = location } targetSrc = location; }); } catch (error) { console.error(error); } this.videoSrc = targetSrc; // 替换 video 标签的src }, 、、、、、、
发现没办法拦截, 仔细对照了获取到的 response 后,发现在代码中实际获取到的 response 并非 302 请求所返回,而是 get 了重定向的后的 response,这里看起来时axios自动进行了重定向并获取了重定向后的response。
那么有没有办法关闭axios的自动重定向行为呢?查阅axios文档时发现axios的一个配置:maxRedirects
但是 maxRedirects 是node环境下的配置,显然不符合业务需求,所以这里pass。而后查阅了文档,并没有看见其他可以处理axios重定向的配置了。如此看来 axios 是无法对302请求进行拦截了,不过为什么axios无法做到拦截302请求呢。
查阅后了资料后发现:
对于XMLHttpRequest而言,readyState = 2 时,此时状态为已经获取到response并且所有的重定向行为都已完成。
大致的流程就是:
ajax -> browser -> server -> 302 -> browser重新get 重定向的 location -> server -> browser -> 回调
综上,看来axios无法做到直接拦截302请求。
不过除了 XMLHttpRequest , 还有 fetch API。
尝试二: 使用fetch API
前面淌了axios的雷,那么这次我们就直接看 fetch 是否支持拦截302请求。
这里发现,fetch API可以支持配置请求重定向处理方式
follow: 跟随跳转(默认)error:阻止跳转并抛出异常(catch)manual:阻止跳转看起来 fetch 所支持的配置刚好可以解决 axios 无法拦截重定向请求的问题,那么接下来就尝试用fetch替代 axios:
、、、、、、 async created() { // 获取302请求返回的location后手动修改video的src路径 let targetSrc; try { await fetch(this.video, { redirect: 'manual' }).then((res) => { const { headers } = res; const { location } = headers; targetSrc = location; }); } catch (error) { console.error(error); } this.videoSrc = targetSrc; // 替换 video 标签的src },、、、、、、
看似这里使用后fetch完美的解决了拦截重定向请求,那么接下来我们直接取到location就可以了。不出意外的话意外要出现了——果然在最后的一步又卡住了。
从 fetch manual模式下输出的获取的response 可以看到不少内容,不过其中的body、hearders、statusText是空的,同时type 属性为 “opaqueredirect”,我们看下图
我们从通过fetch manual 模式下拿到的response 中 type 为 “opaqueredirect”不难看出,此时的response属于“不透明重定向过滤响应”,那么对于该类型响应的特点就是,response 中: status为0、statusText为空、header为空等。没错,headers为空
到了这里,其实已经实现了拦截302请求的目的,但是却无法获得headers中的信息,为此,想要从302请求中获取到location信息仅差一步之遥,那么这里还有什么办法可以获取吗?很遗憾,目前看来 WHATWG 组织认为出于安全考虑,貌似并不太愿意在 opaqueredirect 类型响应中暴露太多信息,其中也包含了所需要的location地址
还有一种场景, 使用fetch请求接口时, 请求不会包含任何凭证。这意味着即使用户已经登录,请求也不会携带cookies或HTTP认证信息。这是credentials : 'omit
' 这个参数的默认行为。
credentials 的选项解释
'omit'
:请求不会包含任何凭证。这意味着即使用户已经登录,请求也不会携带cookies或HTTP认证信息。这是默认行为。
'same-origin'
:请求仅在同源的情况下包含凭证。如果请求的目标URL与请求发起的源(协议、域名、端口)相同,则请求会包含凭证。这是fetch
API的一个常用设置。
'include'
:请求总是包含凭证,无论请求的目标URL是否与请求发起的源相同。这意味着即使是跨域请求也会携带cookies和其他凭证信息。
如果需要携带相关凭证, 可以设置include
fetch('https://example.com/data', { method: 'GET', headers: { 'Content-Type': 'application/json', }, credentials: 'include', // 设置为 include}).then(response => { if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } return response.json();}).then(data => { console.log(data);}).catch(error => { console.error('Fetch error:', error);});
总结
总体看下来,本次尝试并没有找到可以直接拦截重定向请求并获取到location的途径,如果我们有类似的需求场景的话,可能只能取巧了: