Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to intercept all AJAX requests made by different JS libraries

I am building a web app with different JS libraries (AngularJS, OpenLayers,...) and need a way to intercept all AJAX responses to be able, in case the logged user session expired (response gets back with 401 Unauthorized status), to redirect him to the login page.

I know AngularJS offers interceptors to manage such scenarios, but wasn't able to find a way to achieve such injection into OpenLayers requests. So I opted for a vanilla JS approach.

Here I found this piece of 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);

...which I adapted and looks like it behaves as expected (only tested it on last Google Chrome).

As it modifies the prototype of XMLHTTPRequest I am wondering how dangerous this could result or if it could produce serious performance issues. And by the way would there be any valid alternative?

Update: how to intercept requests before they get sent

The previous trick works ok. But what if in the same scenarion you want to inject some headers before the request gets sent? Do the following:

(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);
like image 422
mettjus Avatar asked Aug 15 '14 23:08

mettjus


People also ask

How do I stop multiple AJAX calls?

If isLoading is false, the AJAX call starts, and we immediately change its value to true. Once the AJAX response is received, we turn the value of that variable back to false, so that we can stop ignoring new clicks.

Which library is must for AJAX requests?

Axios. Axios is a modern JavaScript library built on top of XMLHttpRequest for making AJAX calls. It lets you make HTTP requests from both the browser and the server.

Are AJAX requests synchronous?

AJAX can access the server both synchronously and asynchronously: Synchronously, in which the script stops and waits for the server to send back a reply before continuing. Asynchronously, in which the script allows the page to continue to be processed and handles the reply if and when it arrives.

How do you intercept HTTP request in JavaScript?

To intercept HTTP requests, use the webRequest API. This API enables you to add listeners for various stages of making an HTTP request. In the listeners, you can: Get access to request headers and bodies and response headers.


4 Answers

This type of function hooking is perfectly safe and is done regularly on other methods for other reasons.

And, the only performance impact is really only one extra function call for each .open() plus whatever code you execute yourself which is probably immaterial when a networking call is involved.


In IE, this won't catch any code that tries to use the ActiveXObject control method of doing Ajax. Well written code looks first for the XMLHttpRequest object and uses that if available and that has been available since IE 7. But, there could be some code that uses the ActiveXObject method if it's available which would be true through much later versions of IE.


In modern browsers, there are other ways to issue Ajax calls such as the fetch() interface so if one is looking to hook all Ajax calls, you have to hook more than just XMLHttpRequest.

like image 52
jfriend00 Avatar answered Oct 03 '22 02:10

jfriend00


This won't catch XMLHttpRequests for some versions of IE (9 and below). Depending upon the library, they may look for IE's proprietary ActiveX control first.

And, of course, all bets are off if you are using a non-strict DOCTYPE under IE, but I'm sure you knew that.

Reference: CanIuse

like image 30
Jeremy J Starcher Avatar answered Oct 02 '22 02:10

Jeremy J Starcher


As kindly pointed out by by Firefox AMO Editor Rob W,

The following code changes the behavior of XMLHttpRequest. By default, if the third ("async") parameter is not specified, it defaults to true. When it is specified and undefined, it is equivalent to "false", which turns a request in a synchronous HTTP request. This causes the UI to block while the request is being processed, and some features of the XMLHttpRequest API are disabled too.

...

To fix this, replace open.call(....) with open.apply(this, arguments);

And here is a reference link:

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

like image 25
Walty Yeung Avatar answered Oct 02 '22 02:10

Walty Yeung


Try this

let oldXHROpen = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function(method, url, async, user, password) {

console.log({method});

// Show loader

 this.addEventListener('load', function() {
  console.log('load: ' + this.responseText);
  // Hide loader
 });
           
  return oldXHROpen.apply(this, arguments);
}
like image 28
Code Spy Avatar answered Oct 03 '22 02:10

Code Spy