web-dev-qa-db-fra.com

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

Je suis en train de construire 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 le faire, si la session de l'utilisateur connecté expirait (réponse revient avec 401 Unauthorized status), pour le rediriger vers la page de connexion.

Je sais que AngularJS propose interceptors de gérer de tels scénarios, mais n’a pas été en mesure de trouver le moyen de réaliser cette injection dans les requêtes OpenLayers. J'ai donc opté pour une approche Vanilla JS.

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 (testé uniquement sur le dernier Google Chrome).

Comme il modifie le prototype de XMLHTTPRequest, je me demande à quel point cela pourrait être dangereux ou s'il pouvait entraîner de graves problèmes de performances. Et d'ailleurs, 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 demande ne soit envoyée? Faites ce qui 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);
101
mettjus

Ce type de fonction d'accrochage 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’accroche aucun code qui tente d’utiliser la méthode de contrôle ActiveXObject de faire Ajax. Le code bien écrit cherche d’abord pour l’objet XMLHttpRequest et l’utilise s’il est disponible et le reste depuis IE 7. Il est toutefois possible que du code utilise le ActiveXObject s'il est disponible, ce qui serait le cas dans les versions ultérieures d'IE.


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

32
jfriend00

Cela n'acceptera pas XMLHttpRequests pour certaines versions de IE (9 et moins) . Selon la bibliothèque, ils peut rechercher d'abord 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

3
Jeremy J Starcher

Ajax-hook est une bibliothèque open source pour accrocher un objet XMLHttpRequest global et modifie la demande et la réponse Ajax par défaut. github: https://github.com/wendux/Ajax-hook , par exemple:

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])
  }

})
3
wendu

Comme aimablement signalé 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é, sa valeur par défaut est true. Lorsqu'il est spécifié et indéfini, il est équivalent à "false", ce qui transforme une requête en requête HTTP synchrone. Cela provoque le blocage de l'interface utilisateur pendant le traitement de la demande et la désactivation de certaines fonctionnalités de l'API XMLHttpRequest.

...

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

2
Walty Yeung