HTTP応答本文を変更するChrome拡張機能を作成することは可能ですか?
Chrome拡張APIを調べましたが、これを行うための方法が見つかりませんでした。
HTTP応答本文を変更するChrome拡張機能を作成することは可能ですか?
Chrome拡張APIを調べましたが、これを行うための方法が見つかりませんでした。
webRequest.filterResponseData()
。残念ながら、これはFirefoxのみのソリューションです。
回答:
通常、標準のChrome拡張APIを使用してHTTPリクエストの応答本文を変更することはできません。
この機能は104058でリクエストされています:WebRequest API:拡張機能が応答本文を編集できるようにします。問題にスターを付けて、更新の通知を受け取ります。
あなたは、編集に知られているためレスポンスボディたい場合はXMLHttpRequest
、コンテンツのスクリプトによるジェクトコードデフォルト上書きするXMLHttpRequest
(フル機能)カスタム実際のイベントをトリガする前に応答を書き換えて1を持つコンストラクタを。XMLHttpRequestオブジェクトがChromeの組み込みオブジェクトに完全に準拠していることを確認してください。準拠していないとXMLHttpRequest
、AJAXを多用するサイトが破損します。
それ以外の場合は、chrome.webRequest
またはchrome.declarativeWebRequest
APIを使用してリクエストをdata:
-URIにリダイレクトできます。XHRアプローチとは異なり、リクエストの元のコンテンツは取得されません。実際には、リダイレクトは実際の要求が送信される前にしか実行できないため、要求がサーバーに到達することはありません。また、main_frame
リクエストをリダイレクトすると、ユーザーdata:
にはリクエストされたURLの代わりに-URIが表示されます。
data:text...
ですか?
私はちょうどそれを行うDevtools拡張機能をリリースしました:)
これはタンパーと呼ばれ、mitmproxyに基づいており、現在のタブからのすべてのリクエストを確認し、それらを変更して、次に更新するときに変更されたバージョンを提供できます。
これはかなり初期のバージョンですが、OSXおよびWindowsと互換性があるはずです。うまくいかない場合はお知らせください。
ここで入手できますhttp://dutzi.github.io/tamper/
これがどのように機能するか
@Xanが以下にコメントしているように、拡張機能はネイティブメッセージングを介して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の最大の利点の1つは、HTTPS通信も変更できることです。だからあなたもそれを持っています:)
はい。これは、ネットワークAPIを介したHTTPインターセプトと変更をサポートするChromeDevToolsプロトコルchrome.debugger
への拡張アクセスを許可するAPIで可能です。
この解決策は、Chrome Issue487422へのコメントによって提案されました。
現時点で実行可能な代替手段が必要な場合
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
を使用するため、response
代わりに使用するようにObject.definePropertyを変更するだけです