AngularJS intercept API error responses

posted on 2013-08-22

When you work with a security filter on the server end of your AngularJS application, your session may time out resulting in a 401 Unauthorized response. The simplest thing to do is just have the Javascript application reload the page. The filter on the server side can then choose to redirect to a login page.

AngularJS has created intercepters to allow you to have a single place where you cut into all the error responses from the server (HTTP status codes 300 and up).

First some application code that will seem familiar when you have written an AngularJS application:

var App = angular.module('myapp', ['ui']);

App.controller('myController', function ($scope, $http, $timeout) {
    $scope.data = [];
    function update() {
        $http.get("api/data.json").success(function putDataInScope(data) {
            $scope.data = data;
            $timeout(update, 2000);
        }).error(function tryAgainLater() {
            $timeout(update, 2000);
        });
    }
    update();
}

The above code will call GET on api/data.json approximately every two seconds. Now we set up an interceptor by calling config on the App and adding the interceptor to the injected $httpProvider:

App.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.interceptors.push(function ($q) {
        return {
            'response': function (response) {
                //Will only be called for HTTP up to 300
                console.log(response);
                return response;
            },
            'responseError': function (rejection) {
                if(rejection.status === 401) {
                    location.reload();
                }
                return $q.reject(rejection);
            }
        };
    });
}]);

The response property of the returned object is just there for testing purposes. As it will only receive responses that fall below status code 300, there is no use for it when we want to catch 401.

Another thing to note is the responseError handler does not stop the program flow after the location.reload(). As the application I wrote does not have state to save a simple destroy the application by refresh is enough here.

Lastly: the code is for the new interceptors approach, not the deprecated code which uses the responseInterceptors property of the $httpProvider. I've gotten this code to work with version version 1.2.0rc1 of AngularJS.