我如何能够覆盖XMLHttpRequest.open()
方法,然后捕获并更改它的参数?
我已经尝试了代理方法,但它没有用,虽然在调用XMLHttpRequest()
时删除了开放式覆盖:
(function() {
var proxied = window.XMLHttpRequest.open;
window.XMLHttpRequest.open = function() {
$('.log').html(arguments[0]);
return proxied.apply(this, arguments);
};
})();
答案 0 :(得分:36)
您不是要修改open
继承的XMLHttpRequest objects
方法,而只是向XMLHttpRequest constructor
添加一个实际上从未使用过的方法。
我在Facebook上尝试了这段代码,我能够抓住这些请求:
(function() {
var proxied = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function() {
console.log( arguments );
return proxied.apply(this, [].slice.call(arguments));
};
})();
/*
["POST", "/ajax/chat/buddy_list.php?__a=1", true]
["POST", "/ajax/apps/usage_update.php?__a=1", true]
["POST", "/ajax/chat/buddy_list.php?__a=1", true]
["POST", "/ajax/canvas_ticker.php?__a=1", true]
["POST", "/ajax/canvas_ticker.php?__a=1", true]
["POST", "/ajax/chat/buddy_list.php?__a=1", true]
*/
所以是的,open方法需要添加到XMLHttpRequest prototype
(window.XMLHttpRequest.prototype)而不是XMLHttpRequest constructor
(window.XMLHttpRequest)
答案 1 :(得分:3)
我会在Google代码中查看xmlhttprequest project。这是正确覆盖XMLHttpRequest对象的一个很好的例子。可以看到来源here。
答案 2 :(得分:2)
请改用XMLHttpRequest.prototype.open。
答案 3 :(得分:1)
这是我喜欢采取的方法;请注意,掌握XHR猴子补丁的黑暗技巧是一种艺术形式。
将整个套件和缆车包在IIFE中。因此,从以下内容开始:
(function(open, send) {
//...overrides of the XHR open and send methods are now encapsulated within a closure
})(XMLHttpRequest.prototype.open, XMLHttpRequest.prototype.send)
任何一种方法都可以使用这种通用方法来覆盖,但是上面的框架为您提供了一种覆盖XMLHttpRequest的open和send方法的方法(也就是猴子补丁);在一个简洁的实用程序函数中。请注意,如何将“基本”方法(来自API的原型对象)输入到IIFE中,并分别分配给var的“ open”和“ send”,并安全地将其作用于功能块。
现在要勇气了,坚持猴子补丁的关键是什么。再说一次,这就是我的方法,而且有效。
一般模式(均在IIFE范围内)是:
1)复制方法及其参数(根据规范/原型完整地签名),
2)插入您的mod,并且
3)将您的mod应用于XHR原型属性,以确保所有XHR请求都通过您的代码。
例如,“打开”如下所示:
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
xhrOpenRequestUrl = url; // update request url, closure variable
open.apply(this, arguments); // reset/reapply original open method
};
不要挂断xhrOpenRequestUrl = url;行,此代码是从示例中复制的,在该示例中,我需要使用URL进行后续处理。关键要点是“ open.apply”,它将您的调整巩固到XHR open方法中,如果您不熟悉“ apply”方法或“ arguments”对象,那么现在是学习它们的用途的好时机
“发送”方法也是如此...
XMLHttpRequest.prototype.send = function(data) {
//...what ever code you need, i.e. capture response, etc.
if (this.readyState == 4 && this.status >= 200 && this.status < 300) {
xhrSendResponseUrl = this.responseURL;
responseData = this.data; // now you have the data, JSON or whatever, hehehe!
}
send.apply(this, arguments); // reset/reapply original send method
}
同样,“应用”很关键,必须在所有替代操作之后进行。所以现在把它们放在一起...
(function(open, send) {
// Closure/state var's
var xhrOpenRequestUrl; // captured in open override/monkey patch
var xhrSendResponseUrl; // captured in send override/monkey patch
var responseData; // captured in send override/monkey patch
//...overrides of the XHR open and send methods are now encapsulated within a closure
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
xhrOpenRequestUrl = url; // update request url, closure variable
open.apply(this, arguments); // reset/reapply original open method
};
XMLHttpRequest.prototype.send = function(data) {
//...what ever code you need, i.e. capture response, etc.
if (this.readyState == 4 && this.status >= 200 && this.status < 300) {
xhrSendResponseUrl = this.responseURL;
responseData = this.data; // now you have the data, JSON or whatever, hehehe!
}
send.apply(this, arguments); // reset/reapply original send method
}
})(XMLHttpRequest.prototype.open, XMLHttpRequest.prototype.send)
哦,还有最后一件事,您的猴子补丁又可以被猴子补丁了!为了最大程度地减少这种可能性,IIFE代码应放在页面中所有其他JS之后。至少所有可能与XHR混为一谈的JS,但是在您可能要针对的任何AJAX调用之前。同样,可以通过Chrome或Web Extension注入XHR猴子补丁,并且覆盖您的替代!哈!
希望有帮助!