从另一个 JS 脚本重写 JS 脚本的 GET 调用

问题描述 投票:0回答:1

我正在尝试将一些(旧的)动态网站转换为静态页面。到目前为止它工作正常,但我有一些包含的 JS 脚本构建 URL 来加载其他一些 JS 文件,并且 URL 构建很复杂(所以仅仅搜索和替换 URL 是行不通的,我想要一个通用方法)。

我想“重写”从 JS 执行的 GET 调用,以便将它们映射到我自己的(本地)URL。

我尝试使用这个脚本(添加在 HTML 源代码的开头)

console.log("Script loaded");
// Override the open method of XMLHttpRequest to intercept all requests
var originalOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url) {
  console.log("Intercepted HTTP request: " + method + " " + url);
  originalOpen.apply(this, arguments);
};
console.log("Script end");

在首先加载到 HTML 源中的脚本中。在控制台(来自 Firefox 中的 webtools)中,我可以在日志开头(以及“脚本结束”)看到“脚本加载”,但稍后与 JS 脚本关联的网络日志中的“GET ”不会被拦截.

我也尝试过

console.log("Script loaded");
const nativeFetch = window.fetch
window.fetch = async (input, init) => {
  const request = new Request(input, init);
  console.log("request happened!", request.method, request.url);
  return nativeFetch(input, init)
}
console.log("Script end");

具有相同(缺乏)的结果。 注意:两个脚本均来自 StackOverflow 帖子。

在网络控制台中,这些 GET 看起来像:

(method) GET | (domain) <hostname> | (file) <URL path> | (initiator) <the infamous JS script> 

两个脚本都不记录 console.log() 指令,因此看起来没有任何内容被拦截。

我错过了什么吗?执行此操作的正确方法是什么? (如果可以的话)

我的期望:[编辑]我希望每次脚本启动 GET 调用时都能调用我的 JS 函数,以便拦截并修改对我自己的 URL 的调用(我仍然知道)。

[重新编辑]:使过程更加精确。我从一个网站下载一个 HTML 页面(以对其进行统计)。然后我下载所有图像、CSS 和 JS,重写 URL(

src
href
…)以指向本地版本。 但是,当使用网络控制台在 Firefox 中加载页面时,我仍然可以看到来自原始站点 URL 的 GET JS 页面。而这些GET的发起者就是JS脚本。 重写 JS 代码是困难且危险的,所以我试图捕获这些 GET(这里的 GET 是从浏览器的角度来看),以便将它们重新路由到我的本地文件。 希望这更清楚。

javascript get
1个回答
0
投票

我真的无法确定是什么让你的方法不起作用。

但是我建议不要加载拦截器脚本,而是直接将其硬编码在 html 文档中。

此外,最好将拦截器附加到

top
self
window
globalThis

这是一个例子:

console.log('Script loaded!');
{
  
  const exampleLink = 'https://www.w3c.org';
  
  fetch(exampleLink).then
  (
    Result =>
    {
      console.log('Fetching Result:', Result);
    }
  ).catch
  (
    Error =>
    {
      console.log('Fetching Error:', Error.message);
    }
  );
  
  const myRequest = new XMLHttpRequest();
  
  myRequest.addEventListener
  (
    'readystatechange', stateEvent =>
    {
      console.log('XMLHttpRequest open() state changed. New state:', stateEvent.target.readyState);
      
      if ( stateEvent.target.readyState == 4 && stateEvent.target.status == 200 )
      {
        console.log('XMLHttpRequest open() was successful.');
      }
    }
  );
  
  myRequest.addEventListener
  (
    'error', errorEvent =>
    {
      console.log('XMLHttpRequest open() produced an error.');
      console.log('Error:', errorEvent.target.error?.message ?? errorEvent.target.error);
    }
  );
  
  myRequest.open('GET', exampleLink, true);
  
  /*
  .then
  (
    Result =>
    {
      console.log('Fetching Result:', Result);
    }
  ).catch
  (
    Error =>
    {
      console.log('Fetching Error:', Error.message);
    }
  );
  /*/
}
console.log('Script ended!');
<!DOCTYPE html>
<html>
  
  <head>
    
    <!-- This should be your first <script> tag in the document -->
    
    <script>
      
      const originalFetch = fetch;
      const originalOpen = XMLHttpRequest.prototype.open;
      
      try
      {
        top.fetch = fetchInterceptor;
      }
      catch ( Issue )
      {
        console.log('Could not inject the fetch() interceptor at top level.');
        console.log('Issue:', Issue?.message ?? Issue);
      };
      
      self.fetch = fetchInterceptor;
      window.fetch = fetchInterceptor;
      globalThis.fetch = fetchInterceptor;
      
      XMLHttpRequest.prototype.open = openInterceptor;
      
      function fetchInterceptor ()
      {
        console.log('A fetch() got intercepted! Arguments:', arguments);
        return originalFetch.apply(this, arguments);
      }
      
      function openInterceptor ()
      {
        console.log('An open() got intercepted! Arguments:', arguments);
        return originalOpen.apply(this, arguments);
      }
      
      Reflect.setPrototypeOf(fetchInterceptor, originalFetch);
      Reflect.setPrototypeOf(openInterceptor, originalOpen);
      
    </script>
    
    <!-- Any other <script> tag goes after this -->
    
  </head>
  
  <body>
    
    ...
    
  </body>
  
</html>

© www.soinside.com 2019 - 2024. All rights reserved.