1

I found some interesting (and working) answers for how to intercept an ajax call and see all of its content with javascript.(Answer1 and Answer2, ignoring the "timer approach" in answer 2).

I have a Chrome extension that works on a third's page. The page sends and receives its own ajax requests and mostly reshapes itself based on the received data. Currently, my extension can intercept and see the data received, but but it does not interfere in any of the ajax data.

Now I wish to go one step further and change the results before the page reshapes its HTML content!

Example:

User clicks a button, the page itself sends a request and receives a response with an array containing 100 elements to be displayed in a table. The page automatically creates the html table with 100 elements. Everything without my interference.

When the data is received, I can see the 100 elements received.

Now let's say I want the page to show only "50" of those elements instead of 100. How could I change the response received by the page?

Details:

  • The page sends the request, not my extension (I could change the arguments sent, but that is not the best choice, I don't want to send bad requests to the server, which I cannot see or change anyhow).
  • The page itself changes its DOM after receiving the response.
  • I do not want to change the DOM! I need to change the data received before the page starts changing its DOM. (The amount of data received is so huge that the page gets slower than the movement of the continents, I need to prevent the elements from being created)
  • The page is highly dynamic, using one of those "bootstrap-like" frameworks and most of its DOM elements are cleared and recreated each time a response is received.
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Daniel Möller
  • 84,878
  • 18
  • 192
  • 214
  • 1
    [Intercept XMLHttpRequest and modify responseText](http://stackoverflow.com/q/16959359) or [How can I modify the XMLHttpRequest responsetext received by another function?](http://stackoverflow.com/q/26447335) ? – wOxxOm Oct 29 '15 at 13:50
  • Sorry for my last comment, I hadn't noticed the links. Yes! It seems the second link will work. I'll try it when I have the chance! Thank you very much! – Daniel Möller Oct 29 '15 at 14:20
  • 1
    Possible duplicate of [How can I modify the XMLHttpRequest responsetext received by another function?](http://stackoverflow.com/questions/26447335/how-can-i-modify-the-xmlhttprequest-responsetext-received-by-another-function) – Daniel Möller Nov 08 '15 at 16:57
  • Hey @wOxxOm , the second link actually answers my question. If you want to post it as an answer, I'll check it as answered. Thanks :) – Daniel Möller Nov 08 '15 at 16:58

1 Answers1

0

The important part of this method is the Object.defineProperty API.

You can't use object assignment to override, 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>
weiya ou
  • 2,730
  • 1
  • 16
  • 24