如何拦截不同JS库发出的所有AJAX请求


110

我正在使用不同的JS库(AngularJS,OpenLayers等)构建一个Web应用程序,并且需要一种方法来拦截所有AJAX响应,以便在登录的用户会话过期(响应返回401 Unauthorized状态后)的情况下重定向他到登录页面。

我知道AngularJS提供interceptors了管理此类方案的方法,但是无法找到一种方法将这种注入OpenLayers请求中。因此,我选择了普通的JS方法。

在这里,我找到了这段代码...

(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);

...经过改编,看起来像预期的一样(仅在上一个Google Chrome上进行了测试)。

当它修改XMLHTTPRequest的原型时,我想知道这可能导致多么危险,或者是否会产生严重的性能问题。顺便说一句,还有其他有效的选择吗?

更新:如何在请求发送之前拦截请求

上一个技巧可以。但是,如果在同一场景中您想在发送请求之前注入一些标头,该怎么办?请执行下列操作:

(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);

4
对我来说似乎很安全。
2014年

唯一的性能影响是它将在每个AJAX响应期间运行一个额外的功能,但这就是您想要做的。
2014年

我一直在寻找这样的东西。非常感谢
Silver Moon

Answers:


36

这种类型的函数挂钩是非常安全的,并且由于其他原因会定期在其他方法上执行。

而且,唯一的性能影响实际上是每个调用仅一个额外的函数调用,.open()以及您自己执行的任何代码,这在涉及网络调用时可能并不重要。


在IE中,这不会捕获任何试图使用ActiveXObject做Ajax 的控制方法的代码。编写良好的代码将首先查找该XMLHttpRequest对象,并使用该方法(如果可用)以及从IE 7开始就可用的ActiveXObject方法。但是,可能存在一些使用该方法(如果可用)的代码,这在更高版本的IE中都是正确的。


在现代浏览器中,还有其他方法可以发出Ajax调用,例如fetch()接口,因此,如果要挂接所有Ajax调用,则不仅要挂接钩子XMLHttpRequest


1
嗨@ jfriend00 -你将如何挂钩的所有fetch API请求- stackoverflow.com/questions/44728723/...
colemerrick

1
@bagofcole-大概可以对这个fetch()函数进行猴子补丁,以拦截对该函数的所有调用-尽管我自己从未尝试过。看起来这个模块可以做到这一点。
jfriend00

尝试挂钩comment_service_ajax请求时中断YouTube 。
Leeroy

3

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

而且,当然,如果您在IE下使用非严格的DOCTYPE,那么所有赌注都不会成立,但是我敢肯定,您知道这一点。

参考:CanIuse


2

如Firefox AMO编辑器所指出的Rob W

下面的代码更改XMLHttpRequest的行为。默认情况下,如果未指定第三个(“异步”)参数,则默认为true。当它被指定和未定义时,它等效于“ false”,它将在同步HTTP请求中转换一个请求。这将导致UI在处理请求时阻塞,并且XMLHttpRequest API的某些功能也被禁用。

...

要解决此问题,请将open.call(....)替换为open.apply(this,arguments);

这是一个参考链接:

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


(其中“以下代码”是指问题的摘录)
Rob W
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.