DEV Community

artydev
artydev

Posted on

AJAX Request Interceptor

Somtimes you need to trace Ajax call for debugging purpose.
Steve Fenton expose a nice trick to do so :
AJAX Request Interceptor

(function () {
    const arl = new Object();
    arl._open = XMLHttpRequest.prototype.open;
    arl._send = XMLHttpRequest.prototype.send;
    arl.callback = function () {
        const event = new CustomEvent('AjaxDetected', {
            detail: {
                url: this.url,
                method: this.method,
                data: this.data
            }
        });
        document.body.dispatchEvent(event);
    }

    function notNullString(input) {
        return input || '';
    }

    XMLHttpRequest.prototype.open = function (a, b) {
        a = notNullString(a);
        b = notNullString(b);

        arl._open.apply(this, arguments);
        arl.method = a;
        arl.url = b;

        if (a.toLowerCase() == 'get') {
            arl.data = b.split('?');
            arl.data = notNullString(arl.data[1]);
        }
    }

    XMLHttpRequest.prototype.send = function (a, b) {
        a = notNullString(a);
        b = notNullString(b);

        arl._send.apply(this, arguments);

        if (arl.method.toLowerCase() == 'post') {
            arl.data = a;
        }

        arl.callback();
    }
}());
Enter fullscreen mode Exit fullscreen mode

Here is another version :

(function () {
    /**
     * Objet pour logger les requêtes AJAX
     */
    const AjaxRequestLogger = {
        /**
         * Références aux méthodes originales de XMLHttpRequest
         */
        _methodeOriginaleOpen: XMLHttpRequest.prototype.open,
        _methodeOriginaleSend: XMLHttpRequest.prototype.send,

        /**
         * Fonction de callback pour déclencher l'événement personnalisé
         */
        callback: function () {
            const evenement = new CustomEvent('AjaxDetected', {
                detail: {
                    url: this.url,
                    methode: this.methode,
                    donnees: this.donnees
                }
            });
            document.body.dispatchEvent(evenement);
        },

        /**
         * Fonction utilitaire pour retourner une chaîne vide si l'entrée est null ou undefined
         */
        chaineNonNulle: function (entree) {
            return entree || '';
        },

        /**
         * Surcharge de la méthode open de XMLHttpRequest
         */
        surchargerMethodeOpen: function () {
            XMLHttpRequest.prototype.open = function (methode, url) {
                methode = AjaxRequestLogger.chaineNonNulle(methode);
                url = AjaxRequestLogger.chaineNonNulle(url);

                AjaxRequestLogger._methodeOriginaleOpen.apply(this, arguments);
                AjaxRequestLogger.methode = methode;
                AjaxRequestLogger.url = url;

                if (methode.toLowerCase() === 'get') {
                    AjaxRequestLogger.donnees = url.split('?')[1] || '';
                }
            };
        },

        /**
         * Surcharge de la méthode send de XMLHttpRequest
         */
        surchargerMethodeSend: function () {
            XMLHttpRequest.prototype.send = function (donnees) {
                donnees = AjaxRequestLogger.chaineNonNulle(donnees);

                AjaxRequestLogger._methodeOriginaleSend.apply(this, arguments);

                if (AjaxRequestLogger.methode.toLowerCase() === 'post') {
                    AjaxRequestLogger.donnees = donnees;
                }

                AjaxRequestLogger.callback();
            };
        },

        /**
         * Méthode d'initialisation
         */
        initialiser: function () {
            this.surchargerMethodeOpen();
            this.surchargerMethodeSend();
        }
    };

    AjaxRequestLogger.initialiser();
}());

Enter fullscreen mode Exit fullscreen mode

Usage :

document.body.addEventListener('AjaxDetected', function (e) {
    console.log(e.detail.method, e.detail.url, e.detail.data);
}, false);
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
efpage profile image
Eckehard

Last time I needed an Ajax call is so long ago that I hardly remember how to use Ajax at all. The whole concept feels a bit like making fire with two woodsticks...

Image description

Is there any way to add this feature to the fetch-API ?

Collapse
 
artydev profile image
artydev

Hy Eckehard :-)

Look at this Interceptor