IE9 seems to be sending $http.post request to last URL

Situation: I am developing a device application that runs from a single page load and a main module. The application communicates through two API calls. The application requires a current authentication state acquired from an API call to "/api/login" sent via POST. The API call used to save and populate the data of the view renderings is communicated by an API call sent to "/api" via POST. Both calls are made to the same protocol://domain:port.

Problem: In IE9 only, Chrome and FF work as expected, the data returned is not valid for the second API call to "/api". In IE9, the developer tool network panel shows that the call is being made to "/api" with all of the parameters that are suppose to be made. However the response shows a failure response as if I was still making a call to the login api with invalid parameters.

How is this possible even though I am configuring the $http.post to expire immediately on both calls and cache is set to false on both calls? How can I fix it or work around it? Below is the code that I am using.

EDIT: Forgot to mention that I am viewing this from on a Windows 7 ThinkPad.

Code from index.js:

var LocalPortal = angular.module('LocalPortal', ['ngResource'])
.value('lpApi', {
_apiList : [],
_apiUri : '/api',
_functionStack : {},
_host : document.location.hostname,
_port : 8080,
_protocol : document.location.protocol,
_sessionTimeout : 900,
_addToCallStack : function(param) {
  this._functionStack = $.extend(this._functionStack, param);
},
_doApiCall : function(dataSegment, command, params) {
  var segment = {};
  segment[dataSegment] = {"command" : command};
  if (params) {
    segment[dataSegment]["params"] = params;
  }
  this._addToCallStack(segment);
  $.subscribe('api.received', function(e,data) {
    $.publish(command, data[dataSegment]);
  });
},
_restoreAuthState : function() {
  var _authState = (sessionStorage.getItem('lpApi.authState')) ? JSON.parse(sessionStorage.getItem('lpApi.authState')) : {};
  lpApi.authState = _authState;
},
_setAuthTime : function(timeVal) {
  lpApi.authState.authTime = timeVal;
  lpApi._storeAuthState();
},
_storeAuthState : function() {
  sessionStorage.setItem('lpApi.authState', JSON.stringify(lpApi.authState));
},
_url : function() {
  return this._protocol + '//'
          + this._host +
          (this._port ? ':' + this._port : '')
  + this._apiUri;
},
apiList : function() {
  this._doApiCall("apiList", "api.list");
  return this;
},
getPayload : function() {
  var payload = this._functionStack;
  this._functionStack = {};
  return payload;
},
getUrl : function(uriExt) {
  return this._url() + uriExt;
},
init : function(){
  var loc = document.location;

  this._apiList = sessionStorage.getItem('apiList');
  this._host = loc.hostname;
  this._port = loc.port;
  this._protocol = loc.protocol;

  //store a reference to this object for later callbacks to access
  window.lpApi = this;

  //restore authentication state if any
  lpApi._restoreAuthState();
},
logOff : function() {
  lpApi._setAuthTime(0);
  sessionStorage.removeItem('lpApi.authState');
}
})
.config(function($routeProvider) {
$routeProvider.
  when('/login', {templateUrl: 'partials/login.html', controller: LoginCtrl}).
  when('/home', {templateUrl: 'partials/gateway.html', controller: GatewayCtrl}).
  when('/gateway', {templateUrl: 'partials/gateway.html', controller: GatewayCtrl}).
  when('/assets', {templateUrl: 'partials/assets.html', controller: AssetsCtrl}).
  when('/connectivity', {templateUrl: 'partials/connectivity.html', controller: ConnectivityCtrl}).
  when('/events', {templateUrl: 'partials/events.html', controller: EventsCtrl}).
  otherwise({redirectTo:'/home', templateUrl: 'partials/gateway.html', controller: GatewayCtrl});
for (var that in this) {
  if (that.substr(-4) == 'Ctrl') {
    if (this[that].prototype.menu) {
      for (var index in this[that].prototype.menu.items) {
        $routeProvider.
          when(this[that].prototype.menu.items[index].href, {
            templateUrl: this[that].prototype.menu.items[index].template,
            controller: that
          });
      }
    }
    if (this[that].prototype.ctrlActions) {
      for (var index in this[that].prototype.ctrlActions.items) {
        $routeProvider.
          when(this[that].prototype.ctrlActions.items[index].href, {
            templateUrl: this[that].prototype.ctrlActions.items[index].template,
            controller: that
          });
      }
    }
    if (this[that].prototype.mainActions) {
      for (var index in this[that].prototype.mainActions.items) {
        $routeProvider.
          when(this[that].prototype.mainActions.items[index].href, {
            templateUrl: this[that].prototype.mainActions.items[index].template,
            controller: that
          });
      }
    }

    if (this[that].prototype.secondaryActions) {
      for (var index in this[that].prototype.secondaryActions.items) {
        $routeProvider.
          when(this[that].prototype.secondaryActions.items[index].href, {
            templateUrl: this[that].prototype.secondaryActions.items[index].template,
            controller: that
          });
      }
    }
  }
}
})
.directive('appTopMenu', function() {
return {
  restrict: 'E',
  templateUrl: 'partials/top-menu.html'
}
})
.directive('appMenu', function() {
return {
  restrict: 'E',
  templateUrl: 'partials/menu.html',
  link: function(scope,element,attr) {
    for (var that in this) {
      if (that.substr(-4) == 'Ctrl') {
        if (this[that].prototype.menu) {
          for (var index in this[that].prototype.menu.items) {
            scope.menu.items[scope.menu.items.length] = this[that].prototype.menu.items[index];
          }
        }
      }
    }
  }
}
})
.run(function(){
});

var IndexCtrl = function($scope, lpApi, $location) {
//Properties
$scope._localPortalContainer = 'container';

$scope._loggedIn = true;

//Functions
$scope.assertAuthentication = function() {
if(!$scope.isAuthenticated()){
  lpApi.logOff();
  $scope.setRouteReload('/login');
}
};

$scope.getLocalPortalContainer = function() {
return $scope._localPortalContainer;
};

$scope.getLoggedInStatus = function() {
return $scope._loggedIn;
};

$scope.isAuthenticated = function() {
if (sessionStorage) {
  if (sessionStorage.getItem('lpApi.authState')) {
    lpApi.init();
    return ((new Date().getTime() - lpApi.authState.authTime) < 900000);
  }
  else {
    lpApi.init();
    return false;
  }
}
return false;
};

$scope.setErrorMsg = function(msg) {
$scope.errorMsg = msg;
};

$scope.setLocalPortalContainer = function($container){
$scope._localPortalContainer = $container;
};

$scope.setLoggedInStatus = function(status) {
$scope._loggedIn = status;
};

$scope.setRoute = function($route) {
$location.path($route);
};

$scope.setRouteReload = function($route) {
$location.path($route);
document.location.reload();
};

if (!$scope.isAuthenticated()) {
$scope.setLocalPortalContainer('container-small');
$scope.setLoggedInStatus(false);
$scope.setRoute('/login');
}
};

IndexCtrl.$inject = ['$scope', 'lpApi', '$location'];

Code for login.js:

var LoginCtrl = function($scope, $http, lpApi) {

// Functions
$scope.authenticate = function(username, password, $http){
var data = {auth: {username: username, password: password}};

$http.post(lpApi.getUrl('')+'/login', data, {cache: false, headers: {Expires: -1}})
  .error($scope.postError)
  .success($scope.setAuthState);
};

$scope.login = function($scope, lpApi) {
if($scope.isAuthenticated() && lpApi.logOff) {
  lpApi.logOff();
  $scope.setRouteReload('/login');
}
$scope.setLocalPortalContainer('container-small');
$scope.setLoggedInStatus(false);
};

$scope.postError = function(data, status, headers, config){
// output error message
$scope.setErrorMsg(data.errorMessage[0])
};

$scope.setAuthState = function(data, status, headers, config){
lpApi.authState.sessionId = data.sessionId || null;
lpApi.authState.roles = data.roles || null;
lpApi.authState.requirePasswordChange = data.requirePasswordChange || null;
lpApi.authState.success = data.success;
if (data.success) {
  lpApi._setAuthTime(new Date().getTime());
  $scope.setLocalPortalContainer('container');
  $scope.setLoggedInStatus(true);
  $scope.setRoute('/home');
}
else {
  // output error message
  $scope.setErrorMsg(data.errorMessage[0])
}
};

$scope.submit = function(){
$scope.authenticate(this.input_username, this.input_password, $http);
};

$scope.login($scope, lpApi);
};

LoginCtrl.$inject = ['$scope', '$http', 'lpApi'];

Code for gateway.js:

var GatewayCtrl = function($scope, lpApi, $http) {
lpApi.cloudlinkInfo();

lpApi.loggingQuery({limit:"5",page:"0"});

lpApi.modemInfo();

lpApi.osInfo();

lpApi.systemNodeinfo();

lpApi.systemProductinfo();

lpApi.tunnelInfo();

// Properties
$scope.loadData = function(data, status, headers, config) {
console.log('succes'); 
console.log(JSON.stringify(data)); // {"success":false,"errorMessage":["Invalid authentication."]} (See config url is not "/api/login")
console.log(status);
console.log(headers);
console.log(JSON.stringify(config)); // {"method":"POST","url":"protocol://domain:port/api","data":{"cloudlinkInfo": {"command":"cloudlink.info"},"loggingQuery" "command":"logging.query","params":{"limit":"5","page":"0"}},"modemInfo": "command":"modem.info"},"osInfo":{"command":"os.info"},"systemNodeinfo": "command":"system.nodeinfo"},"systemProductinfo" : {"command":"system.productinfo"},"tunnelInfo":{"command":"tunnel.info"}}}
};

$scope.postError = function(data, status, headers, config) {
console.log('error');
console.log(JSON.stringify(data));
console.log(status);
console.log(headers);
console.log(JSON.stringify(config));
};

$scope.assertAuthentication(); // <== asserts we have a current authState.

var payload = lpApi.getPayload(), apiUrl = lpApi.getUrl(''); // <== payload is an object of api calls and their params, apiUrl is protocol://domain:port/api

$http.post(apiUrl, payload).error($scope.postError).success($scope.loadData);
};

GatewayCtrl.$inject = ['$scope', 'lpApi', '$http'];

Answers


The "Invalid Authentication" response was actually a valid response. It turns out the cookie that the device's web service was setting was incomplete according to the expectations of IE9 and IE9 was disregarding it all together. Chrome and FF are so much more forgiving.


Need Your Help

Qt Android: How to show the native file dialog?

android c++ qt qt5 qfiledialog

I'm not sure if it is possible, but currently, when I show an open file dialog:

How to create drop down menu

php html mysql

i'm trying to create dropdown menu, this drop down menu is about name of countries, so when the user for example choose country A then all the posts that are associated with country A will be displ...