拦截并更改ajax调用的结果

Intercept AND CHANGE the results of an ajax call

本文关键字:调用 结果 ajax      更新时间:2023-09-26

我发现了一些有趣的(有效的)答案,说明如何拦截ajax调用并使用javascript查看其所有内容。(答案1和答案2,忽略答案2中的"计时器方法")。

我有一个Chrome扩展,可以在第三方的页面上使用。页面发送和接收自己的ajax请求,并且主要基于接收到的数据来重塑自己。目前,我的扩展可以拦截并查看接收到的数据,但它不会干扰任何ajax数据。

现在,我希望更进一步,在页面重塑其HTML内容之前,更改结果

示例:

用户单击一个按钮,页面本身就会发送一个请求并接收一个包含100个元素的数组的响应,这些元素将显示在表中。页面会自动创建包含100个元素的html表。一切都没有我的干涉。

当收到数据时,我可以看到收到的100个元素。

现在假设我希望页面只显示";50〃;而不是100。如何更改页面收到的响应?

详细信息:

  • 页面发送请求,而不是我的扩展(我可以更改发送的参数,但这不是最好的选择,我不想向服务器发送错误的请求,我无论如何都看不到或无法更改)
  • 页面本身在收到响应后更改其DOM
  • 我不希望更改DOM!在页面开始更改其DOM之前,我需要更改接收到的数据。(收到的数据量如此之大,以至于页面的移动速度比大陆的移动速度慢,我需要防止元素被创建)
  • 该页面是高度动态的;类似引导程序的";每次收到响应时,框架及其大多数DOM元素都会被清除并重新创建

此方法的重要部分是Object.defineProperty API。

不能使用对象分配来覆盖this.responseText = {...};

<button>send</button>
<script>
  const nativeOpen = XMLHttpRequest.prototype.open;
  const nativeSend = XMLHttpRequest.prototype.send;
  const proxiedOpen = function () {
    // Mount the URL that needs to be intercepted to the `XMLHttpRequest` object.
    if (arguments[1].includes('jsonplaceholder.typicode.com/todos/1')) this._url = arguments[1];
    nativeOpen.apply(this, arguments);
  };
  const proxiedSend = async function () {
    if (this._url) {
      // Make other requests, it can also be a fixed value.
      const data = await fetch('https://jsonplaceholder.typicode.com/todos/5').then(res => res.json());
      // The data of `todos/1` is rewritten as `todos/5`
      Object.defineProperty(this, 'responseText', { value: JSON.stringify(data), writable: false });
    }
    nativeSend.apply(this, arguments);
  };
  // Override native methods
  XMLHttpRequest.prototype.open = proxiedOpen;
  XMLHttpRequest.prototype.send = proxiedSend;
  document.querySelector('button').addEventListener('click', () => {
    const xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function () {
      if (this.readyState == 4 && this.status == 200) {
        console.log(this.responseText); // Will get the data of `todos/5` instead of `todos/1`.
      }
    };
    xhttp.open('GET', 'https://jsonplaceholder.typicode.com/todos/1', true);
    xhttp.send();
  });
</script>