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.
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.
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 Standardkonstruktor XMLHttpRequest
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 verwenden chrome.declarativeWebRequest
, um die Anforderung an eine data:
-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 eine main_frame
Anfrage umleiten , wird dem Benutzer die data:
-URI anstelle der angeforderten URL angezeigt.
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 oder subprocess.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 :)
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ür alle, die eine Alternative suchen, die derzeit machbar ist, können Sie sie
chrome.debugger
auf einer Hintergrund- / Ereignisseite verwenden, um sie an die bestimmte Registerkarte anzuhängen, die Sie anhören möchten (oder wenn möglich an alle Registerkarten anhängen, nicht alle Registerkarten persönlich getestet haben). Verwenden Sie dann die Netzwerk-API des Debugging-Protokolls.Das einzige Problem dabei ist, dass sich oben im Ansichtsfenster der Registerkarte der übliche gelbe Balken befindet, es sei denn, der Benutzer schaltet ihn aus
chrome://flags
.
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 entsprechende Request
Objekt sein.
Senden Sie die Antwort mit Network.continueInterceptedRequest
:
rawResponse
.params.interceptionId
as interceptionId
.Beachten Sie, dass ich nichts davon getestet habe.
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 :)
response
anstelle von responseText
, also müssen Sie nur die Object.defineProperty ändern, um response
stattdessen zu verwenden