2009-03-10 6 views

Répondre

0

Vous ne savez pas si vous pouvez le faire avec greasemonkey, mais si vous créez une extension, vous pouvez utiliser le service d'observateur et l'observateur http-on-exam-response.

3

Que diriez-vous de modifier le XMLHttpRequest.prototype.open ou envoyer des méthodes avec des remplacements qui configurent leurs propres callbacks et appellent les méthodes d'origine? Le rappel peut faire son truc, puis appeler le rappel du code original spécifié.

En d'autres termes:

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

Vous pouvez remplacer l'objet unsafeWindow.XMLHttpRequest dans le document avec une enveloppe. Un peu de code (non testé):

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 
    }; 
}; 

Mais cela a un petit problème: les scripts Greasemonkey exécutent après un chargement de la page, de sorte que la page peut utiliser ou stocker l'objet XMLHttpRequest d'origine pendant qu'il est séquence de charge, en fait la demande faite avant l'exécution de votre script, ou avec l'objet XMLHttpRequest réel ne serait pas suivi par votre script. Pas moyen que je puisse voir pour contourner cette limitation.

34

La réponse acceptée est presque correcte, mais il pourrait utiliser une légère amélioration:

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

préfère utiliser + appliquer des arguments sur appel parce que vous n'avez pas de connaître explicitement tous les arguments donnés pour ouvrir ce qui pourrait changer!

0

Testé dans Chrome 55 et Firefox 50.1.0

Dans mon cas, je voulais modifier le responseText, qui dans Firefox était une propriété en lecture seule, donc je devais envelopper tout l'objet XMLHttpRequest. Je n'ai pas implémenté l'ensemble de l'API (en particulier le responseType), mais il était assez bon à utiliser pour toutes les bibliothèques que j'ai.

Utilisation:

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

code:

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