如何拦截不同的JS库所产生的所有AJAX请求

我正在用不同的JS库(AngularJS,OpenLayers,…)构build一个Web应用程序,并且需要拦截所有AJAX响应,以防万一logging的用户会话过期(响应回到401 Unauthorized状态),以将他redirect到login页面。

我知道AngularJS提供interceptors来pipe理这样的场景,但是无法find一种方法来实现OpenLayers的这种注入请求。 所以我select了一个香草JS方法。

在这里我find了这段代码

 (function(open) { XMLHttpRequest.prototype.open = function(method, url, async, user, pass) { this.addEventListener("readystatechange", function() { console.log(this.readyState); // this one I changed }, false); open.call(this, method, url, async, user, pass); }; })(XMLHttpRequest.prototype.open); 

…我调整了它,看起来像预期的行为(只在最后的谷歌浏览器进行testing)。

因为它修改XMLHTTPRequest的原型,我想知道这可能会导致多么危险,或者如果它可能会产生严重的性能问题。 顺便说一下,会有任何有效的select?

更新:如何拦截请求,然后才能发送

以前的技巧工作正常。 但是如果在同一情况下你想在发送请求之前注入一些头部呢? 请执行下列操作:

 (function(send) { XMLHttpRequest.prototype.send = function(data) { // in this case I'm injecting an access token (eg. accessToken) in the request headers before it gets sent if(accessToken) this.setRequestHeader('x-access-token', accessToken); send.call(this, data); }; })(XMLHttpRequest.prototype.send); 

这种types的function挂钩是完全安全的,并由于其他原因定期在其他方法上完成。

而且,唯一的性能影响实际上只有一个额外的函数调用每个.open()加上你自己执行的任何代码,这可能是涉及到networking调用时无关紧要的。


在IE中,这不会捕获任何试图使用Ajax的ActiveXObject控件方法的代码。 编写良好的代码首先查找XMLHttpRequest对象,并使用它,如果可用,并且自IE 7以来已经可用。但是,如果可用的话,可能会有一些使用ActiveXObject方法的代码,通过IE的更新版本可能会发生这种情况。


在现代浏览器中,还有其他一些方式来发出Ajax调用,比如fetch()接口,所以如果你想要挂钩所有的Ajax调用,那么你不得不挂钩XMLHttpRequest

这不会为某些版本的IE (9及以下版本)捕获XMLHttpRequests。 根据库的不同,他们可能会首先查找IE专有的ActiveX控件。

当然,如果您在IE下使用非严格的DOCTYPE,所有的投注都closures,但我相信您知道这一点。

参考: CanIuse

正如Firefox AMO Editor Rob W所指出的那样,

以下代码更改XMLHttpRequest的行为。 默认情况下,如果没有指定第三个(“async”)参数,则默认为true。 当它被指定并且未定义时,它相当于“false”,它在一个同步HTTP请求中转变一个请求。 这会导致UI在请求正在处理时阻塞,并且XMLHttpRequest API的某些function也被禁用。

为了解决这个问题,用open.apply(this,arguments)replaceopen.call(….)。

这里是一个参考链接:

https://xhr.spec.whatwg.org/#the-open()-method