Greasemonkey拦截fetch请求无响应问题排查求助
问题核心错误点
你遇到的问题主要由3个错误导致:
- 调用原生
fetch时丢失了this上下文:原生fetch作为window对象的方法执行时,内部this需要指向window,你直接调用originalFetch(x,y)相当于独立函数调用,严格模式下this为undefined,直接导致请求无法正常发出,这是无请求产生的核心原因。 - 没有处理
fetch的异步特性:fetch返回值是Promise<Response>类型,你直接对Promise实例调用.clone(),操作的根本不是响应对象,完全拿不到返回内容。 - 脚本执行时机/重复执行问题:你在*1位置打印的
originalFetch已经是你覆写后的monitorFetch函数,说明要么你的脚本重复执行,要么脚本执行时机晚于页面对fetch的其他覆写操作,导致你保存的原始fetch本身就是被修改后的版本。
正确实现代码
首先要在用户脚本的元数据块添加@run-at document-start,保证脚本在页面所有其他脚本执行前就完成对fetch的劫持,避免原始方法被提前篡改。
完整代码如下:
// ==UserScript== // @name Fetch响应捕获 // @run-at document-start // ==/UserScript== (function() { // 保存真正的原生fetch const originalFetch = unsafeWindow.fetch; console.log('原始fetch', originalFetch); // 这里打印的应该是原生fetch实现 unsafeWindow.fetch = function (...args) { // 修正this指向,调用原始fetch发起请求 return originalFetch.apply(this, args) .then(response => { // 克隆响应,避免影响原请求的响应消费 const clonedResponse = response.clone(); // 捕获响应内容,这里以打印json格式响应为例 clonedResponse.json() .then(data => { console.log('捕获到响应内容:', data); }) .catch(err => { // 处理非json格式的响应,比如文本、blob等,可按需求调整 clonedResponse.text().then(text => { console.log('捕获到非JSON响应内容:', text); }) }); // 返回原始响应,完全不影响原网站逻辑 return response; }); }; console.log('覆写后的fetch', unsafeWindow.fetch); })();
注意事项
- 如果你只需要捕获特定接口的响应,可以在
fetch调用时先判断请求地址、方法等参数,过滤掉不需要处理的请求,减少性能损耗。 - 对克隆后的响应消费失败不会影响原响应的正常使用,不会干扰网站原有逻辑。
内容的提问来源于stack exchange,提问作者Roman K.
相关产品推荐
相关产品推荐

