拦截和更改ajax调用的结果

时间:2015-10-29 13:31:20

标签: javascript html ajax javascript-events google-chrome-extension

我找到了一些有趣(和工作)的答案,用于拦截ajax调用并使用javascript查看其所有内容。(Answer1Answer2,忽略答案2中的“计时器方法” )。

我有一个chrome扩展程序可以在第三页上运行。页面发送和接收自己的ajax请求,并且主要根据接收的数据重新整形。目前,我的扩展程序可以拦截并查看收到的数据,但它不会干扰任何ajax数据。

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

实施例

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

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

现在让我们说我希望页面只显示那些元素的“50”而不是100.我怎样才能更改页面收到的响应?

详细说明:

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

1 个答案:

答案 0 :(得分:0)

此方法的重要部分是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>