XMLHttpRequest如何拦截请求发送和结果获取?

XMLHttpRequest如何拦截请求发送和结果获取?

我想在发送body参数前捕获到请求并更改body参数,并在得到返回结果的时候拦截做一层处理,请问如何实现?


回答:

很巧,我今年恰好解决了同样的问题。 我的场景是在不污染现有前端库的前提下,记录所有异步请求的耗时。 列出代码,仅供参考,完全能解决你的问题。不要被这么长的代码吓到,最核心的部分只有几行,大部分是我用来计算耗时用的。

(function(open, send) {

window.timing = new Map();

var xhrOpenRequestUrl; // capture method and url

var xhrSendResponseUrl; // capture request body

var responseData; // captured response

XMLHttpRequest.prototype.open = function(method, url, async, user, password) {

xhrOpenRequestUrl = new URL(url, document.location.href).href;

window.timing[xhrOpenRequestUrl] = {

begin: new Date().valueOf(),

method: method

}

open.apply(this, arguments);

};

XMLHttpRequest.prototype.send = function(data) {

this.addEventListener('readystatechange', function() {

var gaPageUrl=document.location.href;

var gaTitle=document.title;

if (window.timing[this.responseURL] && this.readyState === 4) {

xhrSendResponseUrl = this.responseURL;

var duration = new Date().valueOf() - window.timing[xhrSendResponseUrl].begin;

console.log({

hitType: 'timing',

timingCategory: gaTitle + "-" + document.location.href,

timingVar: window.timing[xhrSendResponseUrl].method + ':' + xhrSendResponseUrl ,

timingValue: duration,

timingLabel: JSON.stringify(data)

})

}

}, false);

send.apply(this, arguments);

}

})(XMLHttpRequest.prototype.open, XMLHttpRequest.prototype.send)


回答:

无法拦截。

JS 里内置的 API 除了 Proxy,压根也没提供 AOP(面向切面编程)的能力。

除非你复写它的原型链方法,但极不推荐此做法。因为如果你要做前端埋点或性能监控,你引入的那些库本身就会这么做(比如听云、OneAPM 之类的),你再做了二者就非常容易冲突,况且你复写的玩意儿大概率也不怎么健壮。

但你可以自己封装一层啊,封装层里你想怎么处理就怎么处理呗。需要 AJAX 的调用你自己封装的方法,而不是直接操作 XMLHttpRequest 对象。


P.S. 如果是开发 Chrome 插件那另有办法,但我估计你问的也不是怎么开发插件。


回答:

可以试试这个Ajax-hook


回答:

chrome中大部分api都是可以修改的,就比如你可以修改ajax的send方法,

let oldXHR = window.XMLHttpRequest;

//hook xhr

function newXHR() {

let realXHR = new oldXHR();

let oldSendFun = realXHR.send;

//修改ajax的send方法

realXHR.send = function (body) {

console.log("拦截到消息提",body)

oldSendFun.call(realXHR,body)

}

return realXHR;

}

window.XMLHttpRequest = newXHR;

//这是一个测试用例

let ajax = new XMLHttpRequest();

ajax.open('post', 'inser.php', true);

ajax.send('name=2');

你也可以使用Proxy也可以做拦截,不过我还没试过。

既然说到拦截网络请求了,你也可以了解一下这个Service_Worker_API,虽然这个上手成本高,但是功能应该是最强到的,ajax,fetch,script脚本,css文件中的一些图片请求啥的都能拦截到也能做修改。


回答:

Service Worker 处理这种问题


回答:

'use strict';

;(function () {

if (typeof window.XhrEvent === 'function') return false;

function XhrEvent (event, params) {

params = params || { bubbles: false, cancelable: false, detail: undefined };

var evt = document.createEvent('CustomEvent');

evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);

return evt;

}

XhrEvent.prototype = window.Event.prototype;

window.XhrEvent = XhrEvent;

})();

;(function () {

function xhrEventTrigger (event) {

// eslint-disable-next-line no-undef

var xhrEvent = new XhrEvent(event, { detail: this });

window.dispatchEvent(xhrEvent);

}

var oldXHR = window.XMLHttpRequest;

function newXHR (args) {

var realXHR = new oldXHR(args);

let oldSend = realXHR.send;

realXHR.send = function(data){

this.requestBody = data;

xhrEventTrigger.call(this, 'xhrSendStart');

oldSend.call(this, this.requestBody);

};

// 请求开始

realXHR.addEventListener('loadstart', function () { xhrEventTrigger.call(this, 'xhrLoadStart'); }, false);

// 请求进行中

realXHR.addEventListener('progress', function () { xhrEventTrigger.call(this, 'xhrProgress'); }, false);

realXHR.addEventListener('abort', function () { xhrEventTrigger.call(this, 'xhrAbort'); }, false);

// 请求错误

realXHR.addEventListener('error', function () { xhrEventTrigger.call(this, 'xhrError'); }, false);

// 请求中

realXHR.addEventListener('load', function () { xhrEventTrigger.call(this, 'xhrLoad'); }, false);

// 超时

realXHR.addEventListener('timeout', function () { xhrEventTrigger.call(this, 'xhrTimeout'); }, false);

// 请求完毕

realXHR.addEventListener('loadend', function () { xhrEventTrigger.call(this, 'xhrLoadEnd'); }, false);

// 请求状态改变

realXHR.addEventListener('readystatechange', function () { xhrEventTrigger.call(this, 'xhrReadyStateChange'); }, false);

return realXHR;

}

window.XMLHttpRequest = newXHR;

})();

window.addEventListener('xhrSendStart', function(e){

console.log(e.detail.requestBody);

e.detail.requestBody = '123321';

});

以上是 XMLHttpRequest如何拦截请求发送和结果获取? 的全部内容, 来源链接: utcz.com/p/936271.html

回到顶部