Come intercettare tutte le richieste AJAX effettuate da diverse librerie JS


110

Sto costruendo un'app web con diverse librerie JS (AngularJS, OpenLayers, ...) e ho bisogno di un modo per intercettare tutte le risposte AJAX per poter, nel caso in cui la sessione utente registrata sia scaduta (la risposta torna con lo 401 Unauthorizedstato), reindirizzarlo alla pagina di accesso.

So che AngularJS offre interceptorsdi gestire tali scenari, ma non è stato in grado di trovare un modo per ottenere tale iniezione nelle richieste OpenLayers. Quindi ho optato per un approccio JS vanigliato.

Qui ho trovato questo pezzo di codice ...

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

... che ho adattato e sembra che si comporti come previsto (l'ho testato solo sull'ultimo Google Chrome).

Poiché modifica il prototipo di XMLHTTPRequest, mi chiedo quanto sia pericoloso questo potrebbe risultare o se potrebbe produrre seri problemi di prestazioni. E comunque ci sarebbe qualche valida alternativa?

Aggiornamento: come intercettare le richieste prima che vengano inviate

Il trucco precedente funziona bene. Ma cosa succede se nella stessa scena si desidera iniettare alcune intestazioni prima che la richiesta venga inviata? Eseguire le seguenti operazioni:

(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
Mi sembra perfettamente al sicuro.
Barmar

L'unico impatto sulle prestazioni è che eseguirà una funzione extra durante ogni risposta AJAX, ma è quello che vuoi fare.
Barmar

Stavo cercando qualcosa del genere. grazie mille
Silver Moon

Risposte:


36

Questo tipo di funzione hooking è perfettamente sicuro e viene eseguito regolarmente su altri metodi per altri motivi.

E l'unico impatto sulle prestazioni è in realtà solo una chiamata di funzione extra per ogni .open()più il codice che esegui tu stesso, il che probabilmente è irrilevante quando è coinvolta una chiamata di rete.


In IE, questo non cattura alcun codice che tenta di utilizzare il ActiveXObjectmetodo di controllo per eseguire Ajax. Il codice ben scritto cerca prima l' XMLHttpRequestoggetto e lo utilizza se disponibile e che è stato disponibile da IE 7. Tuttavia, potrebbe esserci del codice che utilizza il ActiveXObjectmetodo, se disponibile, il che sarebbe vero nelle versioni successive di IE.


Nei browser moderni, ci sono altri modi per emettere chiamate Ajax come l' fetch()interfaccia, quindi se si sta cercando di agganciare tutte le chiamate Ajax, è necessario collegare più che solo XMLHttpRequest.


1
Ciao @ jfriend00 - come agganci tutte le richieste di recupero API - stackoverflow.com/questions/44728723/… ?
colemerrick

1
@bagofcole - Potresti presumibilmente riparare la fetch()funzione per intercettare tutte le chiamate ad essa, anche se non l'ho mai provato io stesso. Sembra che questo modulo lo faccia.
jfriend00

Interrompe YouTube durante il tentativo di agganciare le comment_service_ajaxrichieste.
Leeroy

3

Questo non cattura XMLHttpRequests per alcune versioni di IE (9 e precedenti) . A seconda della libreria, possono cercare prima il controllo ActiveX proprietario di IE.

E, naturalmente, tutte le scommesse sono annullate se stai usando un DOCTYPE non rigoroso sotto IE, ma sono sicuro che lo sapevi.

Riferimento: CanIuse


2

Come gentilmente sottolineato da Firefox AMO Editor Rob W,

Il codice seguente modifica il comportamento di XMLHttpRequest. Per impostazione predefinita, se il terzo parametro ("async") non è specificato, il valore predefinito è true. Quando è specificato e non definito, è equivalente a "false", che trasforma una richiesta in una richiesta HTTP sincrona. Ciò causa il blocco dell'interfaccia utente durante l'elaborazione della richiesta e anche alcune funzionalità dell'API XMLHttpRequest sono disabilitate.

...

Per risolvere questo problema, sostituire open.call (....) con open.apply (this, arguments);

Ed ecco un link di riferimento:

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


(dove "Il codice seguente" si riferisce allo snippet della domanda)
Rob W,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.