Currently by using the setTimeout method I am able to successfully do what i want to. But this is not the ideal approach.
When we send a login request, we want to get the CSRF token from the response header and use it insubsequent http calls. The http.get() request does that for us(it sets the login's response header into request header). After that we want to do a post request again based on the response we get from the http.get() request inside the login callback.
The problem here is that the code gets executed before the browser finishes, setting the CSRF token received from response into the request header. In order to overcome this problem, I added a setTimeout function. But I don't really like the approach of adding a hardcoded delay.
Is there any efficient way of doing this?
app.controller('loginCtrl', function ($scope, $http, $location, $cookies, $q, Cart,$rootScope)
{
var defer = $q.defer();
$scope.submit = function(){
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;application/JSON";
//login
$http.post('http://127.0.0.1:8000/api/user/login/', JSON.stringify({'email': $scope.email, 'password': $scope.password})
).success(function(data){
defer.promise.then(function(){
//need to get a cart to check if a cart is created
Cart.getCart(function(data){
defer.promise.then(function(){
//if cart not created create one
if(data.length == 0){
setTimeout(function(){
$http.defaults.headers.common["X-CSRFToken"] = $cookies.csrftoken;
Cart.addCart(function(data){
alert('cart successfully created \n ' + JSON.stringify(data));
$rootScope.cartId = data[0].pk
$rootScope.cart = data[0].fields;
$location.path('/products');
}, function(error){
alert('addcart failed');
});
},300);
} else {
$rootScope.cartId = data[0].pk;
$rootScope.cart = data[0].fields;
$location.path('/products');
}
})
}, function(error){
alert('getcart failed');
});
})
//need code to get the cookies, still dont know how
}).error(function(data){
alert('failure');
});
defer.resolve();
};
});
deferwas introduced in an attempt to make the thing work. As far as I can tell, it's not necessary and can be safely removed. What's left looks like it should work but it would appear that there's some sort of race effect in setting$http.defaults.headers.common["X-CSRFToken"]. Very odd because setting a default header should be reliably synchronous.