Javascript: Overriding XMLHttpRequest.open()
我如何能够覆盖
我已经尝试过代理方法,但是它没有用,尽管在调用
1 2 3 4 5 6 7 | (function() { var proxied = window.XMLHttpRequest.open; window.XMLHttpRequest.open = function() { $('.log').html(arguments[0]); return proxied.apply(this, arguments); }; })(); |
您不是在修改
我在facebook中尝试了此代码,因此能够捕获到请求:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | (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方法添加到
我想看看google code的xmlhttprequest项目。这是正确重写XMLHttpRequest对象的一个??很好的例子。来源可以在这里看到。
这是我喜欢采取的方法;请注意,掌握XHR猴子补丁的黑暗技巧有点像一种艺术形式。
将整个套件和缆车包在IIFE中。因此,请从以下类似内容开始:
1 2 3 | (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请求都通过您的代码。
因此,例如,"打开"如下所示:
1 2 3 4 | 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"对象,那么现在是学习它们的用途的好时机。
同样适用于"发送"方法...
1 2 3 4 5 6 7 8 | 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 } |
同样,"应用"很关键,必须在所有替代操作之后进行。所以现在把它们放在一起...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | (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猴子补丁,并覆盖您的替代!哈!
希望有帮助!
请改用XMLHttpRequest.prototype.open。