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

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.


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


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


(gdzie „Poniższy kod” odnosi się do fragmentu pytania)
— Rob W,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.