Understanding HTTP Interceptors In AngularJS

In a request and response communication of an HTTP call if we want to inject some custom logic the HTTP Interceptor comes into the picture. HTTP Interceptors execute some custom logic before or after the HTTP call.

For example, appending the authentication token to every HTTP request and that token is generated from the client who needs to be validated at the server for security purposes.

These interceptors act as a hook-up for the HTTP calls.

HTTP Interceptors are used for adding custom logic for authentication, authorization, session/state management, logging, modifying Response, URL rewriting, Error handling, Caching, adding a custom header, and time stamp in the request /response, and decrypting the request and response information or manipulate the request and response data over the request cycles.

HTTP Interceptors

HTTP Interceptors are similar to the custom HTTP Module of ASP.NET.

There are four kinds of interceptors in AngularJS - Request, requestError, response, responseError

Syntax for creating HTTP interceptors

var Interceptor = function ($q) {
    return {
        request: function (config) {
            return config;
        },
        requestError: function (rejection) {
            return $q.reject(rejection);
        },
        response: function (result) {
            return result;
        },
        responseError: function (response) {
            return $q.reject(response);
        }
    };
};

interceptorApp = angular.module('interceptorApp', []).config(function ($httpProvider) {
    $httpProvider.interceptors.push(Interceptor);
});

Let us see what these interceptors are and how they are used.

Request

This interceptor is called before $http sends the request to the server. This function takes the request configuration object as an input parameter and returns a configuration object.

When there is a need to add, modify, or remove data prior to sending it to the server for each request the request functions of the interceptors are used.

For example

Let us consider whether we want to insert the authentication token into each request.

request: function (config) {
    console.log('request started...');
    // Validating the requests and assigning the csrf token to each request
    var token = $cookieStore.get("auth");
    config.headers['x-csrf-token'] = token;
    return config;
}

requestError

This interceptor gets called when a request interceptor throws an error or is resolved with a rejection code.

For example

Let us say some error has happened when request interceptors fail and it has blocked the HTTP call, and then log the rejection.

requestError: function (rejection) {
    console.log(rejection);
    // Contains the data about the error on the request and return the promise rejection.
    return $q.reject(rejection);
}

Response

This interceptor is called when the $http receives the response from the server.

This function receives a response object as a parameter to return a response object or a promise. A response interceptor is used to modify the response data or add a new set of values, calling another module or service call.

For example

Let us consider the response that we have got from the service we need to manipulate and add some keys to the result.

response: function (result) {
    console.log('data for ' + result.data.name + ' received');

    // If some manipulation of result is required.
    result["testKey"] = 'testValue';

    console.log('request completed');
    return result;
},

Here result["testKey"] = 'testValue' is added to the result object to the UI Page.

responseError

There are some situations where one call has failed and the application needs to trigger some action based on different HTTP status codes. This interceptor receives a response object as a parameter to return a response object or a promise. The application-level generic error handling is achieved by using this interceptor.

For example

Let us consider the situation of calling the HTTP service call has failed we need to show some error page or login page checking the HTTP status code returned from the server.

responseError: function (response) {
    console.log('response error started...');
    
    // Check different response status and do the necessary actions for 400, 401, 403, or 500 errors
    if (response.status === 401) {
        $location.path('/signin');
        $rootScope.$broadcast('error');
    }
    
    if (response.status === 500) {
        $rootScope.ErrorMsg = "An Unexpected error occured";
        $location.path('/Error');
    }
    
    return $q.reject(response);
}

Code Example of an Interceptor

<!DOCTYPE html>
<html ng-app="interceptorApp">
<head>
    <script src="https://code.angularjs.org/1.4.0-beta.6/angular.js"></script>
    <script>
        var testInterceptor = function ($q) {
            return {
                request: function (config) {
                    console.log('request started...');
                },
                requestError: function (rejection) {
                    console.log(rejection);
                    // Contains the data about the error on the request and return the promise rejection.
                    return $q.reject(rejection);
                },
                response: function (result) {
                    console.log('data for ' + result.data.name + ' received');
                    // If some manipulation of result is required before assigning to scope.
                    result["testKey"] = 'testValue';
                    console.log('request completed');
                    return result;
                },
                responseError: function (response) {
                    console.log('response error started...');
                    // Check different response status and do the necessary actions for 400, 401, 403, or 500 errors.
                    return $q.reject(response);
                }
            };
        };

        var interceptorApp = angular.module('interceptorApp', []).config(function ($httpProvider) {
            $httpProvider.interceptors.push(testInterceptor);
        });

        interceptorApp.controller('interceptorCtrl', ["$scope", "$http",
            function ($scope, $http) {
                $scope.getData = function () {
                    var data = $http.get('http://localhost:52332/testwebapi')
                        .success(function (data, status, headers, config) {
                            $scope.Name = data.name;
                        });
                };
            }
        ]);
    </script>
</head>
<body ng-controller="interceptorCtrl">
    {{ Name }}
    <input type="button" value="Click To Test Interceptors" ng-click="getData()" />
</body>
</html>

Output

Output

We see here that the console log has 'request started...’ and 'response error started...’ from the interceptors.

This was the basic understanding of HTTP Interceptors in AngularJS.

Thanks for reading.