Как перехватить все запросы AJAX, сделанные различными библиотеками JS

Я создаю веб-приложение с различными библиотеками JS (AngularJS, OpenLayers,...) и нужен способ перехватить все ответы AJAX, чтобы иметь возможность, если зарегистрированный сеанс пользователя истек (ответ возвращается с 401 Unauthorized status), чтобы перенаправить его на страницу входа в систему.

Я знаю, AngularJS предлагает interceptors для управления такими сценариями, но не смог найти способ добиться такой инъекции в запросы OpenLayers. Поэтому я выбрал ванильный JS подход.

здесь я нашел этот кусок кода...

(function(open) {

    XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {

        this.addEventListener("readystatechange", function() {
            console.log(this.readyState); // this one I changed
        }, false);

        open.call(this, method, url, async, user, pass);
    };

})(XMLHttpRequest.prototype.open);

...который я адаптировал и выглядит так, как и ожидалось (только протестировал его на последнем Google Chrome).

поскольку он изменяет прототип XMLHTTPRequest, мне интересно, насколько это может быть опасно или может вызвать серьезные проблемы с производительностью. И, кстати, есть ли какая-то действительная альтернатива?

Update: как перехватить запросы, прежде чем они получат отправлен

предыдущий трюк работает нормально. Но что, если в том же сценарии вы хотите ввести некоторые заголовки до отправки запроса? Сделайте следующее:

(function(send) {

    XMLHttpRequest.prototype.send = function(data) {

        // in this case I'm injecting an access token (eg. accessToken) in the request headers before it gets sent
        if(accessToken) this.setRequestHeader('x-access-token', accessToken);

        send.call(this, data);
    };

})(XMLHttpRequest.prototype.send);

4 ответов


этот тип функции закрепляя совершенно безопасен и сделан регулярно на других методах по другим причинам.

и единственное влияние на производительность-это действительно только один дополнительный вызов функции для каждого .open() плюс любой код, который вы выполняете сами, который, вероятно, нематериален, когда задействован сетевой вызов.


в IE это не поймает код, который пытается использовать ActiveXObject метод управления выполнением Ajax. Хорошо написанный код выглядит первым для XMLHttpRequest объект и использует это, если доступно, и это было доступно с IE 7. Но может быть какой-то код, который использует ActiveXObject метод, если он доступен, который был бы истинным через гораздо более поздние версии IE.


в современных браузерах есть и другие способы выдачи вызовов Ajax, такие как fetch() интерфейс поэтому, если вы хотите подключить все вызовы Ajax, вам нужно подключить больше, чем просто XMLHttpRequest.


как любезно указал редактор Firefox AMO Rob W,

следующий код изменяет поведение XMLHttpRequest. По умолчанию, если третий параметр ("async") не указан, по умолчанию используется истинный. Когда он указан и не определен, он эквивалентен " false", который превращает запрос в синхронный HTTP-запрос. В этом случае UI для блокировки во время обработки запроса и некоторые функции API XMLHttpRequest отключены тоже.

...

чтобы исправить это, замените open.призывать.(...) с открытым.применить(это, аргументы);

и вот ссылка:

https://xhr.spec.whatwg.org/#the-open () - метод


Ajax-hook является открытым исходным кодом lib для подключения глобального объекта XMLHttpRequest и изменения запроса и ответа Ajax по умолчанию . github:https://github.com/wendux/Ajax-hook, например:

hookAjax({

  //hook callbacks
  onreadystatechange:function(xhr){
   console.log("onreadystatechange called: %O",xhr)
  },

  onload:function(xhr){
   console.log("onload called: %O",xhr)
  },

  //hook function
  open:function(arg,xhr){
   console.log("open called: method:%s,url:%s,async:%s",arg[0],arg[1],arg[2])
  }

})

Это не поймает XMLHttpRequests для некоторых версий IE (9 и ниже). В зависимости от библиотеки они могут сначала искать собственный элемент управления ActiveX IE.

и, конечно, все ставки отключены, если вы используете нестрогий DOCTYPE под IE, но я уверен, что вы это знали.

ссылки: CanIuse