JavaScript - 拦截XMLHttpRequest

需要做一个扩展,拦截XMLHttpRequest,修改response里面部分值,查阅资料后一般是通过下面方法拦截

let oldOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
    // 拦截open
    // console.log(url)
    return oldOpen.apply(this, arguments);
}

let oldSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(data) {
    console.log(data)  // 发送请求的data
    this.addEventListener('readystatechange', function() {
        // 拦截response
        if (this.readyState === 4) {
            console.log(this.response)
        }
    }, false);
    return oldSend.apply(this, arguments);
}

以上代码没法直接修改responseText,因为他是只读的,如果不用修改responseText的值,只需要判断response的值然后触发相应事件用上面的方法就可以了。
但如果需要修改返回的responseText值则要用下面的办法来更改responseText的get方法

var accessor = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'responseText');
Object.defineProperty(XMLHttpRequest.prototype, 'responseText', {
    get: function() {
        let res = accessor.get.call(this);
        // 在这里对res值进行修改
        console.log(res);
        return res;
    },
    set: function(str) {
        console.log('set responseText: %s', str);
        // return accessor.set.call(this, str);
    },
    configurable: true
});
function setupHook(xhr) {
    function getter() {
        console.log('get responseText');
        delete xhr.responseText;  // 不delete将造成递归
        var res = xhr.responseText;
        setup();
        return res;
    }
    function setter(str) {
        console.log('set response: %s', str);
    }
    function setup() {
        Object.defineProperty(xhr, 'responseText', {
            get: getter,
            set: setter,
            configurable: true
        });
    }
    setup();
}

var oldOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
    if (!this._hooked) {
        this._hooked = true;
        setupHook(this);
    }
    oldOpen.apply(this, arguments);
}
posted @ 2023-06-17 16:42  wstong  阅读(1188)  评论(1编辑  收藏  举报