蘑菇小姐会开花

ajax 重定向跨域问题

最近遇到一个问题:一个页面发ajax请求到后端接口,这个后端接口返回302状态码,并重定向了另外一个域名的地址,此时出现跨域问题

ajax调用浏览器组件发起的请求和浏览器直接发起的请求有一定区别。
1.浏览器可以通过返回的http状态进行相应的操作,如访问一个页面,此页面重定向时,浏览器可以获取到重定向后的url然后进行转向。
2.对于ajax,ajax的目的就是无刷新的,所以对于服务器端进行了重定向时,ajax会获取到重定向状态值3xx和重定向url,然后再获取重定向的页面运行完后输出到客户端的html代码,并且返回200状态。

上面的场景:
1.如果是浏览器发送请求到后端接口,后端接口重定向的话是给浏览器一个302的标示,并且给一个url,浏览器拿到标示后会把地址栏的url换成后端返回的url,完成重定向动作。
2.如果是ajax的话,请求后端接口,后端返回302和一个url,那么ajax会根据htpp的code码做出相对应的动作。接受到的是302那么ajax会再次发起一个请求,去请求服务端302返回的url,那么此时就跨域了。

解决的方式是ajax在第一次得到相应处理后需要js做一次location.href跳转,目的是让浏览器去请求重定向的接口而不是ajax。

于是我就开始想如何将302拦截下来,自己做location.href跳转,由于我的项目用到了axios,我在axios的响应拦截器axios.interceptors.response中开始进行处理,但是怎么都得不到对应的 302 返回结果,最后搜到了这篇文章

文章中提到了这个属性maxRedirects

1
2
3
4
5
6
// axios 在 node 端默认会自动重定向请求
// `maxRedirects` defines the maximum number of redirects to follow in node.js.
// If set to 0, no redirects will be followed.
{
maxRedirects: 5, // default
}

我尝试去修改了这个属性,然而并没有实际效果,后来又搜到了这篇issue
文章中提到在axios取到xhr的响应前,客户端已经完成了重定向的操作。

Client side redirect is being done before axios ever get any response from XHR.

You can’t handle redirects with XHR callbacks because the browser takes care of them automatically. You will only get back what at the redirected location.

我的理解是,当服务器将302响应发给浏览器时,浏览器并不是直接进行ajax回调处理,而是先执行302重定向——从Response Headers中读取location信息,然后向location中的url发出请求,在收到这个请求的响应后才会进行ajax回调处理。
大致流程如下:
ajax -> browser -> server -> 302 -> browser(redirect) -> server -> browser -> ajax callback
所以,在axios的响应中并不能拦截到302请求,于是我继续去看了这篇issue

There is no library that could prevent the redirect. What you need to do on your server-side is distinguish between XHR requests and normal browser navigation requests and send either a 403 w/ JSON and specify the URL you want to redirect to in there or send a 302 if the request is being made by a browser navigation request.

所以最后给出的解决方案是服务端区分ajax请求和浏览器请求,在ajax请求是返回403和需要重定向到的url,在浏览器请求时直接返回302跳转。或者前端直接访问该接口的url,而不要采用ajax。

坚持原创技术分享,您的支持将鼓励我继续创作!