Comment intercepter toutes les requêtes AJAX effectuées par différentes bibliothèques JS

110

Je suis en train de créer une application Web avec différentes bibliothèques JS (AngularJS, OpenLayers, ...) et j'ai besoin d'un moyen d'intercepter toutes les réponses AJAX pour pouvoir, au cas où la session utilisateur enregistrée expirait (la réponse revient avec le 401 Unauthorizedstatut), le rediriger à la page de connexion.

Je sais qu'AngularJS propose interceptorsde gérer de tels scénarios, mais je n'ai pas été en mesure de trouver un moyen de réaliser une telle injection dans les requêtes OpenLayers. J'ai donc opté pour une approche JS vanille.

Ici, j'ai trouvé ce morceau de code ...

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

... que j'ai adapté et qui semble se comporter comme prévu (ne l'a testé que sur le dernier Google Chrome).

Comme il modifie le prototype de XMLHTTPRequest, je me demande à quel point cela pourrait être dangereux ou si cela pourrait produire de graves problèmes de performances. Et au fait, y aurait-il une alternative valable?

Mise à jour: comment intercepter les demandes avant qu'elles ne soient envoyées

L'astuce précédente fonctionne bien. Mais que se passe-t-il si dans le même scénario vous souhaitez injecter des en-têtes avant que la requête ne soit envoyée? Procédez comme suit:

(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
la source
4
Cela me semble parfaitement sûr.
Barmar
Le seul impact sur les performances est qu'il exécutera une fonction supplémentaire lors de chaque réponse AJAX, mais c'est ce que vous voulez faire.
Barmar
Je cherchais quelque chose comme ça. merci beaucoup
Silver Moon

Réponses:

36

Ce type d'accrochage de fonction est parfaitement sûr et se fait régulièrement sur d'autres méthodes pour d'autres raisons.

Et le seul impact sur les performances est en réalité un seul appel de fonction supplémentaire pour chaque .open()plus le code que vous exécutez vous-même, ce qui est probablement sans importance lorsqu'un appel réseau est impliqué.


Dans IE, cela n'attrapera aucun code qui essaie d'utiliser la ActiveXObjectméthode de contrôle de faire Ajax. Un code bien écrit recherche d'abord l' XMLHttpRequestobjet et l'utilise s'il est disponible et qui est disponible depuis IE 7. Mais, il pourrait y avoir du code qui utilise la ActiveXObjectméthode si elle est disponible, ce qui serait vrai dans les versions beaucoup plus récentes d'IE.


Dans les navigateurs modernes, il existe d'autres moyens d'émettre des appels Ajax tels que l' fetch()interface, donc si l'on cherche à raccrocher tous les appels Ajax, vous devez accrocher plus que simplement XMLHttpRequest.

jfriend00
la source
1
Salut @ jfriend00 - comment accrocheriez-vous toutes les requêtes de récupération d'API - stackoverflow.com/questions/44728723/... ?
colemerrick
1
@bagofcole - Vous pourriez probablement monkey-patcher la fetch()fonction afin d'intercepter tous les appels - même si je n'ai jamais essayé cela moi-même. Il semble que ce module fasse cela.
jfriend00
Interrompt YouTube lors de la tentative d'accrochage des comment_service_ajaxdemandes.
Leeroy
3

Cela n'attrapera pas XMLHttpRequests pour certaines versions d'IE (9 et ci-dessous) . En fonction de la bibliothèque, ils peuvent d'abord rechercher le contrôle ActiveX propriétaire d'IE.

Et, bien sûr, tous les paris sont ouverts si vous utilisez un DOCTYPE non strict sous IE, mais je suis sûr que vous le saviez.

Référence: CanIuse

Jeremy J Starcher
la source
2

Comme l'a gentiment souligné par Firefox AMO Editor Rob W,

Le code suivant modifie le comportement de XMLHttpRequest. Par défaut, si le troisième paramètre ("async") n'est pas spécifié, la valeur par défaut est true. Lorsqu'il est spécifié et indéfini, il équivaut à "false", qui transforme une requête en requête HTTP synchrone. Cela provoque le blocage de l'interface utilisateur pendant le traitement de la requête et certaines fonctionnalités de l'API XMLHttpRequest sont également désactivées.

...

Pour résoudre ce problème, remplacez open.call (....) par open.apply (this, arguments);

Et voici un lien de référence:

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

Walty Yeung
la source
(où "Le code suivant" fait référence à l'extrait de la question)
Rob W