跨域请求是目前前端框架式发展中必须解决的问题,目前主流的浏览器均支持cors跨域请求,浏览器无需做过多的处理,在服务器端只需要设置Access-Control-Allow-Origin为*或者是或者是发起这个请求的页面的域名即可。但是IE浏览器只有在IE10及以上版本才支持。
在IE9和IE8浏览器中,I引入了 XDomainRequest 对象。XDomainRequest 对象允许 AJAX 应用程序在满足一定条件的时候,直接发起安全的跨域请求。这个条件是:当数据源指明 HTTP 响应是公共的,并且AJAX应用程序可以确保 HTTP 响应只被当前页面读取。在那种方式下,同源策略安全保证是受到保护的。服务器端也是需要设置Access-Control-Allow-Origin为*或者是或者是发起这个请求的页面的域名即可。
但是这种方式有很大的限制:
1. 必须使用 HTTP 或 HTTPS 协议访问目标 URL
这一条很简单——因为 XDomainRequest 对象依赖于一个HTTP响应头来实现访问控制,XDomainRequest 对象要求目标 URL 符合 HTTP 或 HTTPS 协议,以便于 XDomainRequest 对象检验响应头。检验响应头的目的是为了得到一个允许调用者访问 HTTP 响应的许可。所以,当开发者进行本地测试时需要将测试页面放到web容器中。
2.只能使用 HTTP 的 GET 方法和 POST 方法访问目标 URL
向服务器发送的请求只支持get和post两种方式。但是也基本上能满足我们的基本使用。
3.请求中不能加入自定义的报头
所有XDomainRequest对象发送的请求带有一个 Origin 请求头,显示调用页面的源(域名)。
4.只支持 text/plain 作为请求报头Content-Type的取值
为了应对这个问题,当服务器接收到来自XDomainRequest对象的请求的时候,当前处理HTML表单的服务器代码必须重写,来手动地把请求体解析成名-值对。这使得添加XDomainRequest对象的支持功能变得比原先困难得多。
5.身份验证和cookie不能和请求一起发送
为了阻止对用户的环境验证(比如cookies、HTTP身份验证、客户端证书等等)的误用,请求将会失去cookies和身份验证,并且将会忽略任何身份验证请求或HTTP响应中设置 cookies 的指令。
7.请求URL必须和主页URL采用相同的协议
发送请求的页面协议如果是http,则请求的接口也应该是http协议,如果请求的页面协议为https,则请求的接口也应该为https。
8.返回值没有没有 response status code
在返回值中直接就是返回的数据,不包含状态码等其他数据。
了解了XDomainRequest的一些限制之后,来写一个方法来实现它
function fetchIe9(url, options = {}){ if (window.XDomainRequest) { return new Promise((resolve, reject) => { const method = options.method || 'GET'; const timeout = options.timeout || 30000; let data = options.body || options.params || {}; if (data instanceof Object) { data = JSON.stringify(data); } const XDR = new XDomainRequest(); XDR.open(method, url); XDR.timeout = timeout; XDR.onload = () => { try { const json = JSON.parse(XDR.responseText); return resolve(json.data); } catch (e) { reject(e); } return reject({}); }; // fix random aborting: https://cypressnorth.com/programming/internet-explorer-aborting-ajax-requests-fixed/ XDR.onprogress = () => {}; XDR.ontimeout = () => reject('XDomainRequest timeout'); XDR.onerror = () => reject('XDomainRequest error'); setTimeout(() => { XDR.send(data); }, 0); }); } else { // native fetch or polyfill fetch(XMLHttpRequest) // fetch... }}
领取专属 10元无门槛券
私享最新 技术干货