我正在尝试将一些(旧的)动态网站转换为静态页面。到目前为止它工作正常,但我有一些包含的 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 是从浏览器的角度来看),以便将它们重新路由到我的本地文件。
希望这更清楚。
我真的无法确定是什么让你的方法不起作用。
但是我建议不要加载拦截器脚本,而是直接将其硬编码在 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>