是否可以创建可修改HTTP响应正文的Chrome扩展程序?
我已经查看了Chrome扩展API,但没有找到任何相关方法。
是否可以创建可修改HTTP响应正文的Chrome扩展程序?
我已经查看了Chrome扩展API,但没有找到任何相关方法。
webRequest.filterResponseData()
。不幸的是,这是仅Firefox的解决方案。
Answers:
通常,您无法使用标准的Chrome扩展程序API更改HTTP请求的响应主体。
正在104104处请求此功能:WebRequest API:允许扩展来编辑响应正文。为问题加注星标以获取更新通知。
如果要编辑已知的响应主体XMLHttpRequest
,请通过内容脚本注入代码,XMLHttpRequest
以使用自定义(全功能)的默认构造函数覆盖默认构造函数,该自定义函数在触发真实事件之前会重写响应。确保您的XMLHttpRequest对象与Chrome的内置对象完全兼容XMLHttpRequest
,否则AJAX繁重的网站将崩溃。
在其他情况下,可以使用chrome.webRequest
或chrome.declarativeWebRequest
API将请求重定向到data:
-URI。与XHR方法不同,您不会获得请求的原始内容。实际上,该请求永远不会到达服务器,因为重定向只能在发送实际请求之前完成。而且,如果您重定向main_frame
请求,则用户将看到data:
-URI而不是请求的URL。
data:text...
?
我刚刚发布了一个Devtools扩展程序,它就是这样:)
它被称为篡改,它基于mitmproxy,它使您可以查看当前选项卡发出的所有请求,对其进行修改并在下次刷新时提供修改后的版本。
这是一个相当早期的版本,但是应该与OS X和Windows兼容。让我知道这是否不适合您。
您可以在这里获得它http://dutzi.github.io/tamper/
如何运作
就像@Xan在下面评论的那样,该扩展通过Native Messaging与扩展mitmproxy的python脚本进行通信。
该扩展名使用列出所有请求chrome.devtools.network.onRequestFinished
。
当您单击请求时,它使用请求对象的getContent()
方法下载响应,然后将该响应发送到python脚本,该脚本将其保存在本地。
然后,它将在编辑器中打开文件(call
用于OSX或subprocess.Popen
Windows)。
python脚本使用mitmproxy来侦听通过该代理进行的所有通信,如果它检测到对已保存文件的请求,它将使用已保存的文件。
我使用了Chrome的代理API(特别是chrome.proxy.settings.set()
)将PAC设置为代理设置。该PAC文件将所有通信重定向到python脚本的代理。
关于mitmproxy的最大优点之一是它还可以修改HTTPs通信。所以你也有:)
是。该chrome.debugger
API可以实现,该API授予对Chrome DevTools协议的扩展访问权限,该协议通过其Network API支持HTTP侦听和修改。
此解决方案是由有关Chrome问题487422的评论提出的:
对于目前想要可行的替代方法的任何人,您都可以
chrome.debugger
在后台/事件页面中使用它来附加到您要收听的特定标签上(或尽可能附加到所有标签上,尚未亲自测试过所有标签) ,然后使用调试协议的网络API。唯一的问题是,除非用户在选项卡的视口顶部显示通常的黄色条,否则用户将其关闭
chrome://flags
。
首先,将调试器附加到目标:
chrome.debugger.getTargets((targets) => {
let target = /* Find the target. */;
let debuggee = { targetId: target.id };
chrome.debugger.attach(debuggee, "1.2", () => {
// TODO
});
});
接下来,发送Network.setRequestInterceptionEnabled
命令,将启用对网络请求的拦截:
chrome.debugger.getTargets((targets) => {
let target = /* Find the target. */;
let debuggee = { targetId: target.id };
chrome.debugger.attach(debuggee, "1.2", () => {
chrome.debugger.sendCommand(debuggee, "Network.setRequestInterceptionEnabled", { enabled: true });
});
});
Chrome现在将开始发送Network.requestIntercepted
事件。为他们添加一个监听器:
chrome.debugger.getTargets((targets) => {
let target = /* Find the target. */;
let debuggee = { targetId: target.id };
chrome.debugger.attach(debuggee, "1.2", () => {
chrome.debugger.sendCommand(debuggee, "Network.setRequestInterceptionEnabled", { enabled: true });
});
chrome.debugger.onEvent.addListener((source, method, params) => {
if(source.targetId === target.id && method === "Network.requestIntercepted") {
// TODO
}
});
});
在侦听器中,params.request
将是相应的Request
对象。
发送回复Network.continueInterceptedRequest
:
rawResponse
。params.interceptionId
为interceptionId
。请注意,我根本没有测试过任何一个。
setRequestInterceptionEnabled
方法似乎未包含在DevTools协议v1.2中,我无法找到将其附加到最新版本(树梢)的方法。
chrome.debugger.sendCommand(debuggee, "Network.setRequestInterceptionEnabled", { enabled: true });
因找不到“ Network.setRequestInterceptionEnabled”而失败”
就像@Rob w所说,我已经覆盖了XMLHttpRequest
,这是修改任何站点中任何XHR请求的结果(类似于透明的修改代理):
var _open = XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function (method, URL) {
var _onreadystatechange = this.onreadystatechange,
_this = this;
_this.onreadystatechange = function () {
// catch only completed 'api/search/universal' requests
if (_this.readyState === 4 && _this.status === 200 && ~URL.indexOf('api/search/universal')) {
try {
//////////////////////////////////////
// THIS IS ACTIONS FOR YOUR REQUEST //
// EXAMPLE: //
//////////////////////////////////////
var data = JSON.parse(_this.responseText); // {"fields": ["a","b"]}
if (data.fields) {
data.fields.push('c','d');
}
// rewrite responseText
Object.defineProperty(_this, 'responseText', {value: JSON.stringify(data)});
/////////////// END //////////////////
} catch (e) {}
console.log('Caught! :)', method, URL/*, _this.responseText*/);
}
// call original callback
if (_onreadystatechange) _onreadystatechange.apply(this, arguments);
};
// detect any onreadystatechange changing
Object.defineProperty(this, "onreadystatechange", {
get: function () {
return _onreadystatechange;
},
set: function (value) {
_onreadystatechange = value;
}
});
return _open.apply(_this, arguments);
};
例如,Tampermonkey可以成功使用此代码在任何站点上进行任何修改:)
response
,而不是responseText
,因此,所有你需要做的就是改变Object.defineProperty使用response
代替