2009-03-10 2 views

ответ

0

Не уверен, что вы можете сделать это с помощью greasemonkey, но если вы создадите расширение, вы можете использовать службу наблюдателя и наблюдателя-клиента-наблюдателя.

3

Как модифицировать XMLHttpRequest.prototype.open или отправить методы с заменами, которые устанавливают свои собственные обратные вызовы и вызывают исходные методы? Обратный вызов может выполнить свою задачу, а затем вызвать обратный вызов с указанным исходным кодом.

Другими словами:

XMLHttpRequest.prototype.realOpen = XMLHttpRequest.prototype.open; 

var myOpen = function(method, url, async, user, password) { 
    //do whatever mucking around you want here, e.g. 
    //changing the onload callback to your own version 


    //call original 
    this.realOpen (method, url, async, user, password); 
} 


//ensure all XMLHttpRequests use our custom open method 
XMLHttpRequest.prototype.open = myOpen ; 
1

Вы можете заменить unsafeWindow.XMLHttpRequest объект в документе, с оберткой. Немного кода (не проверено):

var oldFunction = unsafeWindow.XMLHttpRequest; 
unsafeWindow.XMLHttpRequest = function() { 
    alert("Hijacked! XHR was constructed."); 
    var xhr = oldFunction(); 
    return { 
    open: function(method, url, async, user, password) { 
     alert("Hijacked! xhr.open()."); 
     return xhr.open(method, url, async, user, password); 
    } 
    // TODO: include other xhr methods and properties 
    }; 
}; 

Но есть одна маленькая проблема: Greasemonkey скрипты выполнить после загрузки страницы, так что страница может использовать или хранить исходный объект XMLHttpRequest во время его последовательность загрузки, поэтому запросов сделанный до выполнения вашего скрипта, или с реальным объектом XMLHttpRequest, не будет отслеживаться вашим скриптом. Я никак не могу обойти это ограничение.

34

Принятый ответ почти правильно, но он может использовать некоторое улучшение:

(function(open) { 
    XMLHttpRequest.prototype.open = function() { 
     this.addEventListener("readystatechange", function() { 
      console.log(this.readyState); 
     }, false); 
     open.apply(this, arguments); 
    }; 
})(XMLHttpRequest.prototype.open); 

Предпочитают используя применять + аргументы через вызов, потому что тогда вы не имеете явно знать все аргументы, которые даются открытию, которые могут измениться!

0

Испытано в Chrome 55 и Firefox 50.1.0

В моем случае я хотел изменить responseText, что в Firefox было свойство только для чтения, так что мне пришлось обернуть весь объект XMLHttpRequest. Я не реализовал весь API (в частности, responseType), но он был достаточно хорош, чтобы использовать для всех библиотек, которые у меня есть.

Использование:

XHRProxy.addInterceptor(function(method, url, responseText, status) { 
     if (url.endsWith('.html') || url.endsWith('.htm')) { 
      return "<!-- HTML! -->" + responseText; 
     } 
    }); 

Код:

(function(window) { 

    var OriginalXHR = XMLHttpRequest; 

    var XHRProxy = function() { 
     this.xhr = new OriginalXHR(); 

     function delegate(prop) { 
      Object.defineProperty(this, prop, { 
       get: function() { 
        return this.xhr[prop]; 
       }, 
       set: function(value) { 
        this.xhr.timeout = value; 
       } 
      }); 
     } 
     delegate.call(this, 'timeout'); 
     delegate.call(this, 'responseType'); 
     delegate.call(this, 'withCredentials'); 
     delegate.call(this, 'onerror'); 
     delegate.call(this, 'onabort'); 
     delegate.call(this, 'onloadstart'); 
     delegate.call(this, 'onloadend'); 
     delegate.call(this, 'onprogress'); 
    }; 
    XHRProxy.prototype.open = function(method, url, async, username, password) { 
     var ctx = this; 

     function applyInterceptors(src) { 
      ctx.responseText = ctx.xhr.responseText; 
      for (var i=0; i < XHRProxy.interceptors.length; i++) { 
       var applied = XHRProxy.interceptors[i](method, url, ctx.responseText, ctx.xhr.status); 
       if (applied !== undefined) { 
        ctx.responseText = applied; 
       } 
      } 
     } 
     function setProps() { 
      ctx.readyState = ctx.xhr.readyState; 
      ctx.responseText = ctx.xhr.responseText; 
      ctx.responseURL = ctx.xhr.responseURL; 
      ctx.responseXML = ctx.xhr.responseXML; 
      ctx.status = ctx.xhr.status; 
      ctx.statusText = ctx.xhr.statusText; 
     } 

     this.xhr.open(method, url, async, username, password); 

     this.xhr.onload = function(evt) { 
      if (ctx.onload) { 
       setProps(); 

       if (ctx.xhr.readyState === 4) { 
        applyInterceptors(); 
       } 
       return ctx.onload(evt); 
      } 
     }; 
     this.xhr.onreadystatechange = function (evt) { 
      if (ctx.onreadystatechange) { 
       setProps(); 

       if (ctx.xhr.readyState === 4) { 
        applyInterceptors(); 
       } 
       return ctx.onreadystatechange(evt); 
      } 
     }; 
    }; 
    XHRProxy.prototype.addEventListener = function(event, fn) { 
     return this.xhr.addEventListener(event, fn); 
    }; 
    XHRProxy.prototype.send = function(data) { 
     return this.xhr.send(data); 
    }; 
    XHRProxy.prototype.abort = function() { 
     return this.xhr.abort(); 
    }; 
    XHRProxy.prototype.getAllResponseHeaders = function() { 
     return this.xhr.getAllResponseHeaders(); 
    }; 
    XHRProxy.prototype.getResponseHeader = function(header) { 
     return this.xhr.getResponseHeader(header); 
    }; 
    XHRProxy.prototype.setRequestHeader = function(header, value) { 
     return this.xhr.setRequestHeader(header, value); 
    }; 
    XHRProxy.prototype.overrideMimeType = function(mimetype) { 
     return this.xhr.overrideMimeType(mimetype); 
    }; 

    XHRProxy.interceptors = []; 
    XHRProxy.addInterceptor = function(fn) { 
     this.interceptors.push(fn); 
    }; 

    window.XMLHttpRequest = XHRProxy; 

})(window); 

 Смежные вопросы

  • Нет связанных вопросов^_^