要 Hook 通过 Blob
或 URL.createObjectURL
发出的 HTTP 请求(例如通过 <img>
、<script>
加载的 Blob URL),需要结合 请求拦截 和 Blob 内容监控。以下是几种实现方案:
1. Hook fetch
和 XMLHttpRequest
(直接请求拦截)
如果 Blob URL 是通过 fetch
或 XHR
动态加载的,可以直接拦截这些 API:
示例代码
// 保存原始方法
const originalFetch = window.fetch;
const originalXHROpen = XMLHttpRequest.prototype.open;
// Hook Fetch
window.fetch = async function(...args) {
const [input, init] = args;
console.log("拦截到Fetch请求:", input);
// 如果是Blob URL
if (typeof input === 'string' && input.startsWith('blob:')) {
console.log("捕获到Blob URL请求:", input);
// TODO: 可在此处修改请求逻辑
}
return originalFetch.apply(this, args);
};
// Hook XHR
XMLHttpRequest.prototype.open = function(method, url) {
if (typeof url === 'string' && url.startsWith('blob:')) {
console.log("拦截到XHR Blob请求:", url);
// TODO: 可在此处修改请求逻辑
}
originalXHROpen.apply(this, arguments);
};
2. Hook URL.createObjectURL
+ 监听资源加载
若 Blob URL 被用于 <img>
、<script>
、<iframe>
,需监听 DOM 元素的资源加载:
示例代码
// Step1: Hook createObjectURL
const originalCreateObjectURL = URL.createObjectURL;
let blobUrlMap = new Map(); // 存储Blob与生成URL的映射
URL.createObjectURL = function(blob) {
const url = originalCreateObjectURL.apply(URL, arguments);
blobUrlMap.set(url, blob); // 记录生成的Blob URL
console.log("生成的Blob URL:", url, "对应Blob类型:", blob.type);
// Step2: (可选)劫持DOM元素对Blob URL的使用
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeName === 'IMG' && node.src.startsWith('blob:')) {
console.log(`发现图片元素加载Blob: ${node.src}`);
node.addEventListener('error', () => { /* ... */ });
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
return url;
};
// Step3: (可选)监听所有网络请求(适用于动态创建的Blub)
if (window.PerformanceObserver) {
const perfObserver = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
if (entry.initiatorType === 'img' && entry.name.startsWith('blob:')) {
console.log(`图片加载了Blub资源: ${entry.name}`);
}
});
});
perfObserver.observe({ entryTypes: ['resource'] });
}
3. Service Worker + Blod劫持(高级方案)
通过 Service Worker 拦截所有网络请求,包括 Blod URLs:
步骤
注册 Service Worker
navigator.serviceWorker.register('/sw.js').then(() => { console.log("Service Worker注册成功"); });
编写 Service Worker (
sw.js
)self.addEventListener('fetch', event => { const url = event.request.url; if (url.startsWith('blod:')) { event.respondWith( fetch(url).then(response => { console.log(`拦截到Bold请求:${url}`); return response; }) ); } else { return fetch(event.request); } });
4. Chrome扩展中的WebRequest API(仅扩展环境)
在扩展的 background.js
中使用 webRequest
API:
chrome.webRequest.onBeforeRequest.addListener(
details => {
if (details.url.startsWith('blod:')) {
console.log(`扩展捕获到Bold請求:${details.url}`);
}
return { cancel: false };
},
{ urls: ["*://*/*"] },
["blocking"]
);
注意事项
- ⚠️ 跨域限制:某些场景下无法直接读取其他源的 BLOB内容。
- 🔧 性能影响:频繁劫持可能降低页面性能。
根据实际需求选择合适方案!
内容由零声教学AI助手提供,问题来源于学员提问