¿Es posible crear una extensión de Chrome que modifique los cuerpos de respuesta HTTP?
He buscado en las API de extensión de Chrome , pero no he encontrado nada para hacer esto.
¿Es posible crear una extensión de Chrome que modifique los cuerpos de respuesta HTTP?
He buscado en las API de extensión de Chrome , pero no he encontrado nada para hacer esto.
webRequest.filterResponseData()
. Desafortunadamente, esta es una solución solo para Firefox.
Respuestas:
En general, no puede cambiar el cuerpo de respuesta de una solicitud HTTP utilizando las API de extensión estándar de Chrome.
Esta función se solicita en 104058: API WebRequest: permitir que la extensión edite el cuerpo de la respuesta . Destaca el problema para recibir notificaciones de actualizaciones.
Si desea editar el cuerpo de la respuesta para un conocido XMLHttpRequest
, inyecte código a través de una secuencia de comandos de contenido para anular el XMLHttpRequest
constructor predeterminado con uno personalizado (con todas las funciones) que reescribe la respuesta antes de activar el evento real. Asegúrese de que su objeto XMLHttpRequest sea totalmente compatible con el XMLHttpRequest
objeto integrado de Chrome , o los sitios con mucho AJAX se romperán.
En otros casos, puede utilizar las API chrome.webRequest
o chrome.declarativeWebRequest
para redirigir la solicitud a data:
-URI. A diferencia del enfoque XHR, no obtendrá el contenido original de la solicitud. En realidad, la solicitud nunca llegará al servidor porque la redirección solo se puede realizar antes de que se envíe la solicitud real. Y si redirige una main_frame
solicitud, el usuario verá la data:
-URI en lugar de la URL solicitada.
data:text...
?
Acabo de lanzar una extensión de Devtools que hace precisamente eso :)
Se llama tamper, se basa en mitmproxy y le permite ver todas las solicitudes realizadas por la pestaña actual, modificarlas y entregar la versión modificada la próxima vez que actualice.
Es una versión bastante temprana, pero debería ser compatible con OS X y Windows. Avísame si no te funciona.
Puedes conseguirlo aquí http://dutzi.github.io/tamper/
Como funciona esto
Como @Xan comentó a continuación, la extensión se comunica a través de la mensajería nativa con un script de Python que extiende mitmproxy .
La extensión enumera todas las solicitudes que utilizan chrome.devtools.network.onRequestFinished
.
Cuando haces clic en una de las solicitudes, descarga su respuesta utilizando el getContent()
método del objeto de solicitud y luego envía esa respuesta al script de Python que la guarda localmente.
Luego abre el archivo en un editor (usando call
para OSX o subprocess.Popen
para Windows).
La secuencia de comandos de Python usa mitmproxy para escuchar toda la comunicación realizada a través de ese proxy, si detecta una solicitud de un archivo que se guardó, sirve el archivo que se guardó en su lugar.
Usé la API de proxy de Chrome (específicamente chrome.proxy.settings.set()
) para configurar un PAC como configuración de proxy. Ese archivo PAC redirige toda la comunicación al proxy del script de Python.
Una de las mejores cosas de mitmproxy es que también puede modificar la comunicación HTTP. Entonces tienes eso también :)
Si. Es posible con la chrome.debugger
API, que otorga acceso de extensión al Protocolo Chrome DevTools , que admite la interceptación y modificación HTTP a través de su API de red .
Esta solución fue sugerida por un comentario sobre el problema de Chrome 487422 :
Para cualquiera que desee una alternativa que sea factible en este momento, puede usar
chrome.debugger
en una página de fondo / evento para adjuntar a la pestaña específica que desea escuchar (o adjuntar a todas las pestañas si es posible, no he probado todas las pestañas personalmente) , luego use la API de red del protocolo de depuración.El único problema con esto es que habrá la barra amarilla habitual en la parte superior de la ventana gráfica de la pestaña, a menos que el usuario la apague
chrome://flags
.
Primero, adjunte un depurador al destino:
chrome.debugger.getTargets((targets) => {
let target = /* Find the target. */;
let debuggee = { targetId: target.id };
chrome.debugger.attach(debuggee, "1.2", () => {
// TODO
});
});
A continuación, envíe el Network.setRequestInterceptionEnabled
comando, que permitirá la interceptación de solicitudes de red:
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 ahora comenzará a enviar Network.requestIntercepted
eventos. Agrega un oyente para ellos:
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
}
});
});
En el oyente, params.request
estará el Request
objeto correspondiente .
Envía la respuesta con Network.continueInterceptedRequest
:
rawResponse
.params.interceptionId
como interceptionId
.Tenga en cuenta que no he probado nada de esto, en absoluto.
setRequestInterceptionEnabled
método parece no estar incluido en el protocolo DevTools v1.2, y no puedo encontrar una manera de adjuntarlo con la última versión (punta del árbol) en su lugar.
chrome.debugger.sendCommand(debuggee, "Network.setRequestInterceptionEnabled", { enabled: true });
falla con 'Network.setRequestInterceptionEnabled' no se encontró '
Como dijo @Rob w, he anulado XMLHttpRequest
y este es el resultado de la modificación de cualquier solicitud XHR en cualquier sitio (que funciona como un proxy de modificación transparente):
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);
};
por ejemplo, este código puede ser utilizado con éxito por Tampermonkey para realizar modificaciones en cualquier sitio :)
response
más nuevo en lugar de responseText
, por lo que todo lo que tiene que hacer es cambiar Object.defineProperty para usar response
en su lugar