javascript 覆盖XMLHttpRequest.open()

xsuvu9jc  于 2023-02-21  发布在  Java
关注(0)|答案(4)|浏览(137)

我如何能够重写XMLHttpRequest.open()方法,然后捕获并更改它的参数?
我已经尝试过代理方法,但是它不起作用,尽管在调用XMLHttpRequest()时删除了open over-rid:

(function() {
    var proxied = window.XMLHttpRequest.open;
    window.XMLHttpRequest.open = function() {
        $('.log').html(arguments[0]);
        return proxied.apply(this, arguments);
    };
})();
s3fp2yjn

s3fp2yjn1#

您不是在修改XMLHttpRequest objects继承的open方法,而是在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]
*/

因此,需要将打开方法添加到XMLHttpRequest prototype(window.XMLHttpRequest.prototype),而不是XMLHttpRequest constructor(window.XMLHttpRequest)

ecfsfe2w

ecfsfe2w2#

这是我喜欢采用的方法;提醒你一下,掌握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方法的方法(又称猴子补丁);注意"base"方法(来自API的prototype对象)是如何被输入到IIFE中并被分配给var的"open"和"send",以及如何安全地将作用域限定到功能块的。
现在是胆量和什么是坚持你的猴子补丁的关键。现在再一次,这是我如何做它和它的工作。
一般模式(均在综合实地演练的范围内)是:
1)复制方法及其参数(根据规范/原型完整复制签名),
2)穿上你衣服,然后
3)将你的mod应用到XHR prototype属性,以确保所有XHR请求都能通过你的代码。
例如,"open"看起来像:

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调用之前,你可能会成为目标。同样,类似的,XHR猴子补丁可以通过Chrome或Web扩展注入,也可以覆盖你的覆盖!哈!
希望能有所帮助!

pkwftd7m

pkwftd7m3#

我想给予谷歌代码中的xmlhttprequest project,这是一个很好的覆盖XMLHttpRequest对象的例子,源代码可以在here中看到。

t5fffqht

t5fffqht4#

请改用XMLHttpRequest.prototype.open。

相关问题