Kryštof Hilar
Kryštof Hilar

Reputation: 649

Intercepting script load

What I need is to hook/intercept other external JS load. I can place js anywhere in document

Example:

<script src="hook.js"></script>
<script src="a.js"></script>
<script src="b.js"></script>

Hook.js should intercept a.js and b.js. Problem is, that when hook.js is executed, i cannot see other scripts (document.scripts contains only hook.js) and document ready event is too late (scripts a.js and b.js are executed).

Is there any way to "see" other script tags, before are executed ? Thanks for any help

Edit

  1. I need to do any "magic" inside hook.js without modyfing (statically) other HTML.
  2. No jQuery

Upvotes: 5

Views: 3681

Answers (3)

Credit goes here: https://stackoverflow.com/a/59424277/2016831 You can use a MutationObserver to see what elements are being added to the DOM, and when they are being added, simply change the source code, or if its referencing another URL, just redirect it to your own server, with the original URL as a get parameter instead, and return the modified code that way.

Based on the above answer, you could do something like this:

<script>
new MutationObserver((m, o) => {
  let potentialScript = document.querySelector("script + script");
  console.log(potentialScript.textContent);
  if(potentialScript) {
    o.disconnect();
    potentialScript
    .textContent = 
    potentialScript
    .textContent
    .replace(
      "})()",
      `
        window.wow = mySecretMethod;
        })()
      `
    );
    
    
  }
}).observe(
  document.body,
  {
    childList:1
  }
);

</script>

<script>
(function() {
  let mySecretMethod = () => {
    //does a bunch of evil secret stuff
    console.log("HA!");
  };
})();

wow()
</script>

<script>
console.log(wow())
</script>

Alternatively you can redirect the HTTP requests with a chrome extension, see https://stackoverflow.com/a/61202516/2016831 for more

Upvotes: 5

Fabio Beltramini
Fabio Beltramini

Reputation: 2511

If I understand what you're trying to do correctly...

If you can control how scripts A and B are loaded, the best approach is to place them on the same domain as the current page (possibly via proxy), load the files via AJAX, and insert your hooks that way. A library like jQuery as m.casey suggested would make the details of the AJAX and executing the script quite simple.

Otherwise, Javascript does not really have the ability to interact with the parsing of the document (which is what is causing scripts a and b to be loaded in your example, and what would be need to be modified to "intercept" script loading), except by using the evil of document.write to modify the HTML stream. Of course, this only works if hook.js is loaded synchronously (as it is in your example code), if it's loaded into HTML and not XHTML, if you can place a second hook afterwards to postprocess the modified HTML stream, and if you are sure the HTML stream won't escape your mechanism.

For example..

<script id="hook1">document.write("<"+"textarea id='capture'>");</script>
<script src="a.js"></script>
<script src="b.js"></script>
<script id="hook2">document.write("<"+"/textarea");</script>
<script id="hook3">doSomethingWith(document.getElementById("capture").value)</script>

Note that this is a huge hack and you probably shouldn't be doing it.

Upvotes: 1

m.casey
m.casey

Reputation: 2599

If you're using jQuery, you could have hook.js load the scripts you wish to intercept as follows:

$.getScript("a.js");
$.getScript("b.js");

This would dynamically create the script tags and you would be certain that hook.js would always proceed a.js and b.js.

Upvotes: 0

Related Questions