Можно ли создать расширение Chrome, изменяющее тела ответов HTTP?
Я просмотрел API-интерфейсы расширений Chrome , но не нашел ничего для этого.
google-chrome-extension
капитан дракон
источник
источник
webRequest.filterResponseData()
. К сожалению, это решение только для Firefox.Ответы:
Как правило, вы не можете изменить тело ответа HTTP-запроса с помощью стандартных API-интерфейсов расширения Chrome.
Эта функция запрашивается по адресу 104058: API WebRequest: разрешить расширению редактировать тело ответа . Пометьте проблему, чтобы получать уведомления об обновлениях.
Если вы хотите отредактировать тело ответа для известного
XMLHttpRequest
, введите код через сценарий содержимого, чтобы заменитьXMLHttpRequest
конструктор по умолчанию пользовательским (полнофункциональным), который перезаписывает ответ перед запуском реального события. Убедитесь, что ваш объект XMLHttpRequest полностью совместим со встроеннымXMLHttpRequest
объектом Chrome , иначе сайты с AJAX-загрузкой сломаются.В других случаях вы можете использовать API-интерфейсы
chrome.webRequest
илиchrome.declarativeWebRequest
для перенаправления запроса наdata:
-URI. В отличие от XHR-подхода, вы не получите исходное содержимое запроса. Фактически, запрос никогда не попадет на сервер, потому что перенаправление может быть выполнено только до отправки фактического запроса. А если вы перенаправитеmain_frame
запрос, пользователь увидитdata:
-URI вместо запрошенного URL.источник
data:text...
?Я только что выпустил расширение Devtools, которое делает именно это :)
Это называется tamper, он основан на mitmproxy и позволяет вам видеть все запросы, сделанные текущей вкладкой, изменять их и обслуживать измененную версию при следующем обновлении.
Это довольно ранняя версия, но она должна быть совместима с OS X и Windows. Сообщите мне, если это не сработает для вас.
Вы можете получить его здесь http://dutzi.github.io/tamper/
Как это работает
Как прокомментировал @Xan ниже, расширение обменивается данными через собственный обмен сообщениями с помощью скрипта python, который расширяет mitmproxy .
В расширении перечислены все запросы, использующие
chrome.devtools.network.onRequestFinished
.Когда вы щелкаете по запросу, он загружает свой ответ, используя метод объекта запроса
getContent()
, а затем отправляет этот ответ скрипту python, который сохраняет его локально.Затем он открывает файл в редакторе (используется
call
для OSX илиsubprocess.Popen
для Windows).Сценарий python использует mitmproxy для прослушивания всех сообщений, передаваемых через этот прокси, если он обнаруживает запрос на файл, который был сохранен, он вместо этого обслуживает файл, который был сохранен.
Я использовал API прокси-сервера Chrome (в частности
chrome.proxy.settings.set()
), чтобы установить PAC в качестве настройки прокси. Этот файл PAC перенаправляет все сообщения на прокси-сервер сценария python.Одна из величайших особенностей mitmproxy заключается в том, что он также может изменять связь по протоколу HTTP. Так что у вас тоже есть :)
источник
Да. Это возможно с помощью
chrome.debugger
API, который предоставляет расширению доступ к протоколу Chrome DevTools , который поддерживает перехват и изменение HTTP через свой сетевой API .Это решение было предложено в комментарии к проблеме 487422 Chrome :
Сначала прикрепите к цели отладчик:
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
вместо