Я уже пробовал прокси-метод, но он не работал, хотя удалял открытый избыточный код при вызове XMLHttpRequest()
:
Ответ 1
Вы не изменяете метод open
, унаследованный XMLHttpRequest objects
, а просто добавляете метод к XMLHttpRequest constructor
, который на самом деле никогда не используется.
Я пробовал этот код в facebook, и мне удалось поймать запросы:
(function() {
var proxied = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function() {
console.log( arguments );
return proxied.apply(this, [].slice.call(arguments));
};
})();
/*
["POST", "/ajax/chat/buddy_list.php?__a=1", true]
["POST", "/ajax/apps/usage_update.php?__a=1", true]
["POST", "/ajax/chat/buddy_list.php?__a=1", true]
["POST", "/ajax/canvas_ticker.php?__a=1", true]
["POST", "/ajax/canvas_ticker.php?__a=1", true]
["POST", "/ajax/chat/buddy_list.php?__a=1", true]
*/
Итак, открытый метод должен быть добавлен в XMLHttpRequest prototype
(window.XMLHttpRequest.prototype) не XMLHttpRequest constructor
(window.XMLHttpRequest)
Ответ 4
Вот подход, который мне нравится использовать; имейте в виду, освоение темного искусства XHR обезьяна патч это своего рода искусство.
Оберните весь комплект и кабачок в IIFE. Итак, начните с чего-то вроде следующего:
(function(open, send) {
//...overrides of the XHR open and send methods are now encapsulated within a closure
})(XMLHttpRequest.prototype.open, XMLHttpRequest.prototype.send)
Любые методы могут быть переопределены с использованием этого общего подхода, но приведенные выше скаффолдинги предоставляют вам способ переопределить (также известный как патч обезьяны) как методы open, так и send для XMLHttpRequest; в одной аккуратной функции полезности. Обратите внимание, как "базовые" методы (из объекта-прототипа API) подаются в IIFE и назначаются для переменных "open" и "send" и безопасно ограничиваются функциональным блоком.
Теперь для смелости и что является ключом к сохранению вашего обезьяньего патча. Опять же, вот как я это делаю, и это работает.
Общая схема (все в пределах IIFE) заключается в следующем:
1) повторить метод и его аргументы (подпись, полностью, согласно спецификации/прототипу),
2) проскользнуть в ваш мод и
3) примените ваш мод к свойству прототипа XHR, чтобы все запросы XHR проходили через ваш код.
Так, например, "open" будет выглядеть так:
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
xhrOpenRequestUrl = url; // update request url, closure variable
open.apply(this, arguments); // reset/reapply original open method
};
Не зацикливайтесь на xhrOpenRequestUrl = url; строка, этот код скопирован из примера, где мне понадобился URL для дальнейшей обработки. Ключ к выводу "open.apply", он скрепляет ваши настройки в методе XHR open, если вы не знакомы с методом "apply" или объектом "arguments", то сейчас самое время узнать, что они делают,
И аналогично для метода "отправить"...
XMLHttpRequest.prototype.send = function(data) {
//...what ever code you need, i.e. capture response, etc.
if (this.readyState == 4 && this.status >= 200 && this.status < 300) {
xhrSendResponseUrl = this.responseURL;
responseData = this.data; // now you have the data, JSON or whatever, hehehe!
}
send.apply(this, arguments); // reset/reapply original send method
}
Опять же, "применить" имеет решающее значение, и это должно быть сделано после всех ваших переопределений. Так что теперь все вместе...
(function(open, send) {
// Closure/state var's
var xhrOpenRequestUrl; // captured in open override/monkey patch
var xhrSendResponseUrl; // captured in send override/monkey patch
var responseData; // captured in send override/monkey patch
//...overrides of the XHR open and send methods are now encapsulated within a closure
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
xhrOpenRequestUrl = url; // update request url, closure variable
open.apply(this, arguments); // reset/reapply original open method
};
XMLHttpRequest.prototype.send = function(data) {
//...what ever code you need, i.e. capture response, etc.
if (this.readyState == 4 && this.status >= 200 && this.status < 300) {
xhrSendResponseUrl = this.responseURL;
responseData = this.data; // now you have the data, JSON or whatever, hehehe!
}
send.apply(this, arguments); // reset/reapply original send method
}
})(XMLHttpRequest.prototype.open, XMLHttpRequest.prototype.send)
О, и последнее, ваш патч обезьяны, в свою очередь, может быть патчирован обезьяной! Чтобы минимизировать эту возможность, код IIFE должен идти после всех остальных JS на странице. По крайней мере, все JS, которые могут быть обезьянами с XHR, но перед любыми вызовами AJAX, на которые вы, возможно, нацеливаетесь. Кроме того, аналогичным образом, патч XHR-обезьяны может быть введен через Chrome или веб-расширение, а также отменяет переопределение! ХА!
Надеюсь, это поможет!