如果你的 Blob 生成的代码(例如动态创建的脚本或 Worker)中的 JavaScript 请求没有经过你的代理服务器,而你希望对这些请求进行 Hook,可以通过以下方法实现:
1. Hook fetch
/ XMLHttpRequest
全局对象
在 Blob 代码执行前,覆盖全局的 fetch
和 XMLHttpRequest
,确保所有请求都经过你的代理逻辑。
示例:Hook fetch
// 保存原生 fetch
const originalFetch = window.fetch;
// 重写 fetch
window.fetch = async function(...args) {
const [input, init] = args;
let url = typeof input === 'string' ? input : input.url;
// 修改 URL,使其经过你的代理服务器
if (!url.startsWith('http://your-proxy/')) {
url = 'http://your-proxy/?target=' + encodeURIComponent(url);
}
console.log('Proxied request:', url);
// 使用修改后的 URL 发起请求
return originalFetch(url, init);
};
示例:Hook XMLHttpRequest
const originalXHR = window.XMLHttpRequest;
window.XMLHttpRequest = class extends originalXHR {
open(method, url, async, user, password) {
// 修改 URL,使其经过代理服务器
if (!url.startsWith('http://your-proxy/')) {
url = 'http://your-proxy/?target=' + encodeURIComponent(url);
}
console.log('Proxied XHR request:', url);
super.open(method, url, async, user, password);
}
};
2. Hook importScripts
(适用于 Web Workers)
如果 Blob 代码运行在 Worker/Service Worker 中,可以劫持 importScripts()
:
const originalImportScripts = self.importScripts;
self.importScripts = function(...urls) {
const proxiedUrls = urls.map(url =>
'http://your-proxy/?target=' + encodeURIComponent(url)
);
console.log('Proxied importScripts:', proxiedUrls);
return originalImportScripts.apply(this, proxiedUrls);
};
3. Monkey Patch <script>
/动态加载的 JS
如果 Blob 是通过 <script>
、<iframe>
、或者动态插入的 JS (document.createElement('script')
)执行的:
// Hook document.createElement("script")
const originalCreateElement = document.createElement;
document.createElement = function(tagName) {
if (tagName.toLowerCase() === 'script') {
const scriptEl = originalCreateElement.call(this, tagName);
// Hook src setter
Object.defineProperty(scriptEl, 'src', {
set: function(value) {
const proxiedUrl = 'http://your-proxy/?target=' + encodeURIComponent(value);
scriptEl.setAttribute('src', proxiedUrl); // Apply proxy URL
},
get: function() { return this.getAttribute('src'); }
});
return scriptEl;
}
return originalCreateElement.call(this, tagName);
};
4. Service Worker:拦截所有网络请求
如果是浏览器环境,可以注册一个 Service Worker,拦截所有 HTTP(S) 请求:
// sw.js (Service Worker)
self.addEventListener('fetch', (event) => {
const requestUrl = event.request.url;
if (!requestUrl.includes('your-proxy')) { // Avoid infinite loop!
const proxyUrl = new URL(requestUrl);
// Modify the request to go through your proxy server:
proxyUrl.hostname = 'your-proxy-server.com';
event.respondWith(
fetch(proxyUrl.toString())
.catch(err => fetch(event.request)) // Fallback to direct fetch on error
);
console.log(`Intercepted and rerouted: ${requestUrl} → ${proxyUrl}`);
}
});
然后注册它:
navigator.serviceWorker.register('/sw.js');
5. Node.js / Puppeteer:直接替换全局对象
如果你使用 Puppeteer/Cypress/Selenium,可以在页面加载前注入脚本:
await page.evaluateOnNewDocument(() => {
window.fetch = new Proxy(window.fetch, { /* ... */ });
window.XMLHttpRequest = new Proxy(window.XMLHttpRequest, { /* ... */ });
});
总结
方法 | 适用场景 |
---|---|
Hook fetch/XHR |
Blob/Worker/Dynamic Script |
Hook importScripts() |
Web Workers |
Monkey Patch <script> |
Dynamic JS Injection |
Service Worker Interception | Browser-wide Request Control |
Puppeteer Injection | Automated Testing |
选择最适合你场景的方法进行拦截和代理! 🚀
内容由零声教学AI助手提供,问题来源于学员提问