Interceptez XMLHttpRequest et modifiez responseText

J'essaie de créer un script qui servira de proxy / wrapper à l'objet natif XMLHttpRequest , ce qui me permet de l'intercepter, de modifier le ResponseText et de revenir à l'événement original onreadystatechange.

Le contexte étant, si les données que l'application tente de recevoir sont déjà disponibles dans le stockage local, annuler le XMLHttpRequest et transmettre les données stockées localement dans les méthodes de rappel de succès / échec des applications. Supposons que je n'ai aucun contrôle sur les applications des méthodes de rappel AJAX existantes.

J'avais essayé à l'origine l'idée suivante …

 var send = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function(data){ //Do some stuff in here to modify the responseText send.call(this, data); }; 

Mais comme je l'ai déjà établi, le responseText est en lecture seule.

J'ai ensuite essayé de reculer, en écrivant mon propre proxy natif complet vers XMLHttpRequest , finissant finalement par écrire ma propre version des méthodes natives. Semblable à ce qui est discuté ici …

Http://www.ilinsky.com/articles/XMLHttpRequest/#implementation-wrapping

Mais il a rapidement été confus et a toujours la difficulté de renvoyer les données modifiées dans la méthode originale onReadyStateChange .

Aucune suggestion? Est-ce même possible?

 // // firefox, ie8+ // var accessor = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'responseText'); Object.defineProperty(XMLHttpRequest.prototype, 'responseText', { get: function() { console.log('get responseText'); return accessor.get.call(this); }, set: function(str) { console.log('set responseText: %s', str); //return accessor.set.call(this, str); }, configurable: true }); // // chrome, safari (accessor == null) // var rawOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function() { if (!this._hooked) { this._hooked = true; setupHook(this); } rawOpen.apply(this, arguments); } function setupHook(xhr) { function getter() { console.log('get responseText'); delete xhr.responseText; var ret = xhr.responseText; setup(); return ret; } function setter(str) { console.log('set responseText: %s', str); } function setup() { Object.defineProperty(xhr, 'responseText', { get: getter, set: setter, configurable: true }); } setup(); } 

Votre step-back est une overkill: vous pouvez ajouter votre propre getter sur XMLHttpRequest: ( plus sur les propriétés )

 Object.defineProperty(XMLHttpRequest.prototype,"myResponse",{ get: function() { return this.responseText+"my update"; // anything you want } }); 

l'usage:

 var xhr = new XMLHttpRequest(); ... console.log(xhr.myResponse); // xhr.responseText+"my update" 

Note sur les navigateurs modernes que vous pouvez exécuter xhr.onload (voir les conseils XMLHttpRequest2 )

Le script suivant intercepte parfaitement les données avant d'envoyer via XMLHttpRequest.prototype.send

 <script> (function(send) { XMLHttpRequest.prototype.send = function(data) { this.addEventListener('readystatechange', function() { }, false); console.log(data); alert(data); }; })(XMLHttpRequest.prototype.send); </script>