Jak przechwycić wszystkie żądania AJAX wysyłane przez różne biblioteki JS

110

Buduję aplikację internetową z różnymi bibliotekami JS (AngularJS, OpenLayers, ...) i potrzebuję sposobu na przechwycenie wszystkich odpowiedzi AJAX, aby móc, w przypadku wygaśnięcia sesji zalogowanego użytkownika (odpowiedź wraca ze 401 Unauthorizedstatusem), przekierować go do strony logowania.

Wiem, że AngularJS oferuje interceptorszarządzanie takimi scenariuszami, ale nie byłem w stanie znaleźć sposobu na osiągnięcie takiego wstrzyknięcia do żądań OpenLayers. Więc zdecydowałem się na waniliowe podejście do JS.

Tutaj znalazłem ten fragment kodu ...

(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);

... który dostosowałem i wygląda na to, że zachowuje się zgodnie z oczekiwaniami (testowałem go tylko na ostatnim Google Chrome).

Ponieważ modyfikuje prototyp XMLHTTPRequest, zastanawiam się, jak niebezpieczne może to spowodować lub czy może spowodować poważne problemy z wydajnością. A tak przy okazji, czy byłaby jakaś ważna alternatywa?

Aktualizacja: jak przechwytywać żądania, zanim zostaną wysłane

Poprzednia sztuczka działa dobrze. Ale co, jeśli w tym samym scenariuszu chcesz wstrzyknąć niektóre nagłówki, zanim żądanie zostanie wysłane? Wykonaj następujące czynności:

(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);
mettjus
źródło
4
Wydaje mi się całkowicie bezpieczne.
Barmar
Jedyny wpływ na wydajność polega na tym, że będzie uruchamiać dodatkową funkcję podczas każdej odpowiedzi AJAX, ale właśnie to chcesz zrobić.
Barmar
szukałem czegoś takiego. wielkie dzięki
Silver Moon

Odpowiedzi:

36

Ten typ podpinania funkcji jest całkowicie bezpieczny i jest wykonywany regularnie innymi metodami z innych powodów.

Jedyny wpływ na wydajność to tak naprawdę tylko jedno dodatkowe wywołanie funkcji dla każdego .open()plus kod, który sam wykonujesz, co prawdopodobnie nie ma znaczenia, gdy w grę wchodzi połączenie sieciowe.


W IE to nie przechwyci żadnego kodu, który próbuje użyć ActiveXObjectmetody kontroli wykonywania Ajax. Dobrze napisany kod szuka najpierw XMLHttpRequestobiektu i używa go, jeśli jest dostępny, i był dostępny od IE 7. Ale może istnieć kod, który używa tej ActiveXObjectmetody, jeśli jest dostępna, co byłoby prawdą w znacznie późniejszych wersjach IE.


W nowoczesnych przeglądarkach istnieją inne sposoby wywoływania Ajax, takie jak fetch()interfejs, więc jeśli ktoś chce przechwycić wszystkie wywołania Ajax, musi to zrobić więcej niż tylko XMLHttpRequest.

jfriend00
źródło
1
Cześć @ jfriend00 - jak możesz przechwycić wszystkie żądania pobierania API - stackoverflow.com/questions/44728723/… ?
colemerrick
1
@bagofcole - Przypuszczalnie można by małpa łatać tę fetch()funkcję, aby przechwytywać wszystkie wywołania do niej - chociaż sam nigdy tego nie próbowałem. Wygląda na to , że ten moduł to robi.
jfriend00
Przerywa YouTube podczas próby przechwytywania comment_service_ajaxżądań.
Leeroy
3

To nie spowoduje przechwycenia XMLHttpRequests dla niektórych wersji IE (9 i poniżej) . W zależności od biblioteki mogą najpierw szukać zastrzeżonego formantu ActiveX IE.

I, oczywiście, wszystkie zakłady są wyłączone, jeśli używasz nieostrożnego DOCTYPE w IE, ale jestem pewien, że o tym wiedziałeś.

Odniesienie: CanIuse

Jeremy J Starcher
źródło
2

Jak uprzejmie zaznaczył Firefox AMO Editor Rob W,

Poniższy kod zmienia zachowanie XMLHttpRequest. Domyślnie, jeśli trzeci („asynchroniczny”) parametr nie jest określony, domyślnie przyjmuje wartość true. Gdy jest określony i niezdefiniowany, jest równoważny z wartością „false”, która zamienia żądanie w synchroniczne żądanie HTTP. Powoduje to blokowanie interfejsu użytkownika podczas przetwarzania żądania, a niektóre funkcje interfejsu API XMLHttpRequest są również wyłączone.

...

Aby to naprawić, zamień open.call (....) na open.apply (this, arguments);

A oto link referencyjny:

https://xhr.spec.whatwg.org/#the-open()-method

Walty Yeung
źródło
(gdzie „Poniższy kod” odnosi się do fragmentu pytania)
Rob W,