Search code examples
angularjssessionangular-http-interceptors

Configure angular $http with a value obtained from server


I'm building my (first) angular app that will have tokens inserted into headers (the content shown is for the most part taken from here)

angular.module('myApp')

.factory('sessionInjector', ['SessionService', function(SessionService) {  
   var sessionInjector = {
        request: function(config) {
            config.headers['x-session-token'] = SessionService.getToken();
            return config;
        }
    };
    return sessionInjector;
}])

.config(['$httpProvider', function($httpProvider) {  
    $httpProvider.interceptors.push('sessionInjector');
}])

The trouble I'm having is with SessionService - how can I initialize this with call to the server?

For example, this didn't work:

.factory('SessionService', ['$injector', function($injector){
    var token = "";

    return {
        getToken: function () {
            var http = $injector.get('$http');
            if (token === "") {
                http.get('http://localhost/api/auth/getToken').success(function (ret) {
                    token = ret;
                });
            }
            return token; 
            //I can see a $q/deferred/promise should be used somehow here... 
            //but I'm not sure it solves the problem I'm having...
        }
    }
}]);

because it just overloads my cpu to 100%...

Since it's my first angular app, I'm sure I'm missing something, but... what?

EDIT:
Another take on the matter... still doesn't work though... (again, uses up cpu, probably infinite loop)

  .factory('sessionData', function () {
    var currentToken = '[uninitialized-token]';

    return {
        getToken: function () {
            return currentToken;
        },
        setToken: function (token) {
            currentToken = token;
        }
    }
})

.factory('sessionInjector', ['sessionData', '$injector', '$q', function (sessionData, $injector, $q) {
    var sessionInjector = {
        request: function (config) {
            var deferred = $q.defer();
            var http = $injector.get('$http');
            http.get('http://localhost/api/auth/getToken').success(function (ret) {
                sessionData.setToken(ret);
                console.log("successfully authenticated with token " + sessionData.getToken());
                config.headers['x-header-sessionID'] = sessionData.getToken();
                deferred.resolve(config);
            })
            .error(function(){
                console.log("failed to authenticate");
                deferred.resolve(config);
            });

            return deferred.promise;
        }
    };
    return sessionInjector;
}])

.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.interceptors.push('sessionInjector');
}])

.run(['$http', 'sessionData', function ($http, configs, sessionData) {
    $http.get('http://localhost/api/auth/testMethod').then(function (ret) {
        //do something...
    });
}])

Solution

  • Answer was actually pretty straight forward - if the targeted URL is for login, then don't inject anything (look for the comment the fix):

    .factory('sessionData', function () {
        var currentToken = '[uninitialized-token]';
    
        return {
            getToken: function () {
                return currentToken;
            },
            setToken: function (token) {
                currentToken = token;
            }
        }
    })
    
    .factory('sessionInjector', ['sessionData', '$injector', '$q', function (sessionData, $injector, $q) {
        var sessionInjector = {
            request: function (config) {
    
                //The fix:
                if(config.url === 'http://localhost/api/auth/getToken')
                    return config;
    
                var deferred = $q.defer();
                var http = $injector.get('$http');
                http.get('http://localhost/api/auth/getToken').success(function (ret) {
                    sessionData.setToken(ret);
                    console.log("successfully authenticated with token " + sessionData.getToken());
                    config.headers['x-header-sessionID'] = sessionData.getToken();
                    deferred.resolve(config);
                })
                .error(function(){
                    console.log("failed to authenticate");
                    deferred.resolve(config);
                });
    
                return deferred.promise;
            }
        };
        return sessionInjector;
    }])
    
    .config(['$httpProvider', function ($httpProvider) {
        $httpProvider.interceptors.push('sessionInjector');
    }])
    
    .run(['$http', 'sessionData', function ($http, configs, sessionData) {
        $http.get('http://localhost/api/auth/testMethod').then(function (ret) {
            //do something...
        });
    }])