拦截 XMLHttpRequest 并修改 responseText
我正在尝试构建一个脚本,它将充当本机 XMLHttpRequest
对象的代理/包装器,使我能够拦截它、修改 responseText 并返回到原始的 onreadystatechange 事件.
I'm trying to build a script that will act as a proxy/wrapper for the native XMLHttpRequest
object enabling me to intercept it, modify the responseText and return back to the original onreadystatechange event.
上下文是,如果应用程序尝试接收的数据已经在本地存储中可用,则中止 XMLHttpRequest
并将本地存储的数据传递回应用程序的成功/失败回调方法.假设我无法控制应用现有的 AJAX 回调方法.
The context being, if the data the app is trying to receive is already available in local storage, to abort the XMLHttpRequest
and pass the locally stored data back into the apps success/failure callback methods. Assume I have no control over the apps existing AJAX callback methods.
我最初尝试了以下想法..
I had originally tried the following idea..
var send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(data){
//Do some stuff in here to modify the responseText
send.call(this, data);
};
但正如我现在所建立的,responseText 是只读的.
But as I have now established, the responseText is read only.
然后我尝试退后一步,为 XMLHttpRequest
编写我自己的完整本机代理,最终编写了我自己的本机方法版本.类似于这里讨论的...
I then tried taking a step back, writing my own full native proxy to XMLHttpRequest
, ultimately ending up writing my own version of the native methods. Similar to what is discussed here...
http://www.ilinsky.com/articles/XMLHttpRequest/#implementation-wrapping
但它很快就变得混乱了,并且仍然很难将修改后的数据返回到原始的 onReadyStateChange
方法中.
But it rapidly got confusing, and still have the difficulty of returning the modified data back into the original onReadyStateChange
method.
有什么建议吗?这甚至可能吗?
Any suggestions? Is this even 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();
}
相关文章