Ist es möglich, eine Chrome-Erweiterung zu erstellen, die HTTP-Antwortkörper ändert?
Ich habe in den Chrome-Erweiterungs-APIs nachgesehen , aber nichts dafür gefunden.
google-chrome-extension
Kapitän Drache
quelle
quelle
webRequest.filterResponseData()
. Leider ist dies eine reine Firefox-Lösung.Antworten:
Im Allgemeinen Sie können nicht die Antwort Körper einer HTTP - Anforderung ändern , um die Standard - Chrome - Erweiterung APIs.
Diese Funktion wird unter 104058 angefordert : WebRequest-API: Erweiterung zum Bearbeiten des Antworttextes zulassen . Markieren Sie das Problem, um über Updates informiert zu werden.
Wenn Sie den Antworttext für einen bekannten bearbeiten möchten
XMLHttpRequest
, fügen Sie Code über ein Inhaltsskript ein , um den StandardkonstruktorXMLHttpRequest
mit einem benutzerdefinierten (voll ausgestatteten) Konstruktor zu überschreiben, der die Antwort neu schreibt, bevor das reale Ereignis ausgelöst wird.XMLHttpRequest
Stellen Sie sicher, dass Ihr XMLHttpRequest-Objekt vollständig mit dem in Chrome integrierten Objekt kompatibel ist. Andernfalls werden AJAX-lastige Websites beschädigt.In anderen Fällen können Sie die APIs
chrome.webRequest
oder verwendenchrome.declarativeWebRequest
, um die Anforderung an einedata:
-URI umzuleiten. Im Gegensatz zum XHR-Ansatz erhalten Sie nicht den ursprünglichen Inhalt der Anfrage. Tatsächlich wird die Anfrage niemals den Server erreichen, da die Umleitung nur erfolgen kann, bevor die eigentliche Anfrage gesendet wird. Wenn Sie einemain_frame
Anfrage umleiten , wird dem Benutzer diedata:
-URI anstelle der angeforderten URL angezeigt.quelle
data:text...
?Ich habe gerade eine Devtools-Erweiterung veröffentlicht, die genau das tut :)
Es heißt Tamper, basiert auf Mitmproxy und ermöglicht es Ihnen, alle von der aktuellen Registerkarte gestellten Anforderungen anzuzeigen , zu ändern und die geänderte Version beim nächsten Aktualisieren bereitzustellen.
Es ist eine ziemlich frühe Version, sollte aber mit OS X und Windows kompatibel sein. Lassen Sie mich wissen, wenn es bei Ihnen nicht funktioniert.
Sie können es hier bekommen http://dutzi.github.io/tamper/
Wie das funktioniert
Wie @Xan weiter unten kommentiert, kommuniziert die Erweiterung über Native Messaging mit einem Python-Skript, das Mitmproxy erweitert .
Die Erweiterung listet alle Anforderungen mit auf
chrome.devtools.network.onRequestFinished
.Wenn Sie auf eine der Anforderungen klicken, wird die Antwort mithilfe der
getContent()
Methode des Anforderungsobjekts heruntergeladen und anschließend an das Python-Skript gesendet, das sie lokal speichert.Anschließend wird die Datei in einem Editor geöffnet (unter
call
OSX odersubprocess.Popen
Windows).Das Python-Skript verwendet Mitmproxy, um die gesamte Kommunikation über diesen Proxy abzuhören. Wenn es eine Anforderung für eine gespeicherte Datei erkennt, wird die stattdessen gespeicherte Datei bereitgestellt.
Ich habe die Proxy-API von Chrome (speziell
chrome.proxy.settings.set()
) verwendet, um einen PAC als Proxy-Einstellung festzulegen. Diese PAC-Datei leitet die gesamte Kommunikation an den Proxy des Python-Skripts weiter.Eines der größten Dinge bei Mitmproxy ist, dass es auch die HTTP-Kommunikation ändern kann. Also hast du das auch :)
quelle
Ja. Dies ist mit der
chrome.debugger
API möglich, die Erweiterungszugriff auf das Chrome DevTools-Protokoll gewährt , das das Abfangen und Ändern von HTTP über die Netzwerk-API unterstützt .Diese Lösung wurde durch einen Kommentar zu Chrome Issue 487422 vorgeschlagen :
Fügen Sie zunächst einen Debugger an das Ziel an:
chrome.debugger.getTargets((targets) => { let target = /* Find the target. */; let debuggee = { targetId: target.id }; chrome.debugger.attach(debuggee, "1.2", () => { // TODO }); });
Senden Sie als Nächstes den
Network.setRequestInterceptionEnabled
Befehl, der das Abfangen von Netzwerkanforderungen ermöglicht: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 beginnt nun mit dem Senden von
Network.requestIntercepted
Ereignissen. Fügen Sie einen Listener für sie hinzu: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 } }); });
Im Listener
params.request
wird das entsprechendeRequest
Objekt sein.Senden Sie die Antwort mit
Network.continueInterceptedRequest
:rawResponse
.params.interceptionId
asinterceptionId
.Beachten Sie, dass ich nichts davon getestet habe.
quelle
setRequestInterceptionEnabled
Methode scheint nicht im DevTools-Protokoll v1.2 enthalten zu sein, und ich kann keine Möglichkeit finden, sie stattdessen mit der neuesten Version (Tip-of-Tree) zu verknüpfen.chrome.debugger.sendCommand(debuggee, "Network.setRequestInterceptionEnabled", { enabled: true });
schlägt fehl mit 'Network.setRequestInterceptionEnabled' wurde nicht gefunden 'Wie @Rob w sagte, habe ich überschrieben
XMLHttpRequest
und dies ist ein Ergebnis für die Änderung von XHR-Anforderungen auf beliebigen Websites (funktioniert wie ein transparenter Änderungs-Proxy):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); };
Zum Beispiel kann dieser Code von Tampermonkey erfolgreich verwendet werden, um Änderungen an Websites vorzunehmen :)
quelle
response
anstelle vonresponseText
, also müssen Sie nur die Object.defineProperty ändern, umresponse
stattdessen zu verwenden