How to re try operation after refresh token - jquery ajax - javascript

In my flow say i am using an access token for getting my data. When my access token expires i get a 401 error i am using the refresh token to get a new access token.
Note : My access token and refresh token is stored in a cookie and i am updating the same after a 401 error.
My question how do i retry the same operation which i was in the middle of?
My Code (services.js):
var refresh_token = "na";
function get_api_data(url, api_token) {
var returnData = handleApiData(url, api_token, "GET");
return returnData;
}
function post_api_data(url, api_token, post_data) {
var returnData = handleApiData(url, api_token, "PUT", post_data);
return returnData;
}
function handleApiData(url, access_token, type, post_data) {
return $.ajax({
url: url,
type: type,
data: post_data,
error: failHandler,
contentType: "application/json",
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + access_token);
}
})
}
function handleData(data, textStatus, jqXHR) {
return data;
}
function failHandler(jqXHR, textStatus, errorThrown) {
switch (jqXHR.status) {
case 401:
var api = get_api_token();
checkApiToken(api.refresh_token);
break;
default:
alert(errorThrown);
}
}
function checkApiToken(refresh_token) {
if (refresh_token != "na") {
$.post("/Account/Refresh/?refresh_token=" + refresh_token);
//location.reload();
}
}
My Code (notification.js):
$(function () {
var api = get_api_token();
if (api != null)
get_notification_data(api.access_token);
});
function get_notification_data(api_token) {
var notifications = get_api_data(urls.notifications.list, api_token);
if (notifications != undefined)
notifications.success(function (data) {
items = data.records;
_.each(items, function (item) {
item.Status = ko.observable(item.status);
item.onClick = function () {
if (item.Status() === 'UNREAD') {
var post_data = { id: item.id };
post_api_data(urls.notifications.list, api_token, post_data).success(function (response, textStatus) {
if (response.success)
item.Status('READ');
$(location).attr("href", item.action_link);
});
}
else {
$(location).attr("href", item.action_link);
}
}
});
var model = {
items: ko.observableArray(items),
onCancel: function (item) {
}
}
ko.applyBindings(model, $("#notificationBar")[0]);
})
}
Edit: My AccountController code that sets the new API cookie:
[HttpPost]
public ActionResult Refresh(string refresh_token)
{
string token_string = string.Empty;
try
{
token_string = OAuthHelper.getTokenViaRefreshTokenFromAPIServer(refresh_token);
if(token_string != null)
Response.Cookies[Constants.Cookies.API].Value = token_string;
}
catch (Exception ex)
{
Log.Info(string.Format("AccountController.cs -Refresh Token Error ", ex.Message));
}
return RedirectToAction("Index","Home");
}

Related

how to cache ajax response in browser and retrieve value from cache browser

I want to cache ajax response into browser database so that i can retrieve the reponse from another web page of the same application.
so far i have tried but i am not able to retrieve the data from browser cache.
any help will be appreciated
this my setting.js
appsetting = {
service1: 'http://localhost:59190/api/Settings/GetConfigurationSettings',
settingsdata: {},
savesettings: function (data) {
//alert('success');
console.log(data);
appsetting.settingsdata = data;
},
getsettings: function () {
var token = { 'token': '00000000-0000-0000-0000-000000000000' };
DBconnection.fetchdata('GET', appsetting.service1, appsetting.savesettings, function () { console.log('Cannot fetch pos') }, token, true);
}
}
this is ajaxcall.js
DBconnection = {
localCache: {
timeout: 30000,
data: {},
remove: function (url) {
delete DBconnection.localCache.data[url];
},
exist: function (url) {
return !!DBconnection.localCache.data[url] && ((new Date().getTime() - DBconnection.localCache.data[url]._) < DBconnection.localCache.timeout);
},
get: function (url) {
console.log('Getting in cache for url' + url);
return DBconnection.localCache.data[url].data;
},
set: function (url, cachedData, callback) {
DBconnection.localCache.remove(url);
DBconnection.localCache.data[url] = {
_: new Date().getTime(),
data: cachedData
};
if ($.isFunction(callback)) callback(cachedData);
}
},
fetchdata: function (typeofcall, url, success, failure, header, cachedata) {
$.ajax({
type: typeofcall,
url: url,
dataType: 'json',
failure: failure,
success: success,
headers: header,
cache: cachedata
});
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
if (options.cache) {
var complete = originalOptions.complete || $.noop,
url = originalOptions.url;
//remove jQuery cache as we have our own localCache
options.cache = false;
options.beforeSend = function () {
if (DBconnection.localCache.exist(url)) {
complete(DBconnection.localCache.get(url));
return false;
}
return true;
};
options.complete = function (data, textStatus) {
DBconnection.localCache.set(url, data, complete);
};
}
});
}
}
on my webpage i am trying to call like this
var setting = appsetting.getsettings();
console.log(setting);
but i am getting undefined result.

JSON.parse unexpected end of input error in NodeJS MailParser

I am executing a code in NodeJS child_process.
I used MailParser of Andris9.
I used console.log(JSON.stringify({obj:mail_object})); to get the data of mail_object to the parent.
In the parent, I have this code, JSON.parse(retVal);.
The error came up is "Unexpected end of Input".
This error only shows when the email I received is having an attachment.
If the email doesnt have attachment, there is no error.
Here is the parent method,
getEmails(){
let workerProcess = child_process.spawn('node', [basePath+'imports/workers/retrieveEmail.js']);
workerProcess.stdout.on('data', function (data) {
try{
let retVal = new Buffer(data).toString();
retVal = JSON.parse(retVal);
console.log(retVal);
if(typeof retVal.err == "undefined"){
console.log(retVal.obj.from[0].address);
Fiber(function () {
var objs = [];
if (typeof retVal.obj.attachments !== "undefined") {
console.log("Test passed");
retVal.obj.attachments.forEach(function (attachment) {
let future = new Future();
Fiber(function () {
Files.write(attachment.content, {
fileName: attachment.fileName,
type: attachment.contentType
}, function (error, fileRef) {
if (error) {
future.throw(new Meteor.Error(500, error.message));
} else {
...
}
});
}).run();
var bool = true;
if (bool = future.wait())
objs.push(bool);
});
}
...
}).run();
}else{
console.log(retVal.err);
}
}catch(e){
console.log(e);
}
});
workerProcess.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
workerProcess.on('close', function (code) {
console.log('child process exited with code ' + code);
});
},
I removed some unnecessary codes.
Here is my retrieveEmail.js,
...
client.on("retr", function (status, msgnumber, data, rawdata) {
if (status === true) {
var mailparser = new MailParser({
streamAttachments: false
});
var timeStamp = Math.floor(Date.now());
mailparser.on("attachment", function (attachment, mail) {
console.log(JSON.stringify({err:"testpassed1"}));
});
mailparser.on("end", function (mail_object) {
console.log(JSON.stringify({err:"testpassed2"}));
console.log(JSON.stringify({obj:mail_object}));
});
mailparser.write(data);
mailparser.end();
client.dele(msgnumber);
} else {
console.log("RETR failed for msgnumber " + msgnumber);
client.quit();
}
});
...

AngularJS $http.post/service issue

I have a weird problem.. when I am loading my details page, the error part gets executed first in the controller.
Though the service myService gets executed and it does return value, in the controller error is executed and I am not getting my message details.
I have put an alert in service before and jsonObj is valid.
controller:
url = 'http://' + add + ':8080/user/site.cgi';
data = {
ACTION : "list",
STATS : "no"
};
myService.getdata(url, data)
.then(function(data, status, headers, config) {
$timeout(function(){
if (data.body.response.status == "OK") {
if (data.body.response.msg.id) {
service2.seturl(data.body.response.msg.id, username, add);
messg.push(data.body.response.msg);
} else
angular.forEach(data.body.response.msg, function(value, key) {
service2.seturl(value.id, username, add);
messg.push(value);
})
$rootScope.messg = messg;
} else {
errorMessage = data.body.response.errmsg;
alert(errorMessage);
}
}, 5000);
}, function(error, status, headers, config) {
alert("Check network connection.."); //Coming here without fulfilling promise.
});
}
services:
.service('myService', function($http, $q, $httpParamSerializerJQLike) {
return {
getdata: function(url, data) {
var postData = data;
return $http({
method : 'POST',
url : url,
data : $httpParamSerializerJQLike(postData)
}).then(function(response, status, headers, config) {
var x2js = new X2JS();
var jsonObj = x2js.xml_str2json(response.data);
if (typeof jsonObj === 'object') {
alert(jsonObj); //I am getting this alert just fine.
return jsonObj; //It does return the object.
} else {
return $q.reject(jsonObj);
}
}, function(response, status, headers, config) {
return $q.reject(response.data);
});
}
}
})
.factory('service2', function() {
var urls = [{ }];
return {
all: function() {
return urls;
},
geturl: function(id) {
for (var i = 0; i < urls.length; i++) {
if (urls[i].id === parseInt(id)) {
return urls[i];
}
}
return null;
},
seturl: function(id, admin, add) {
for (var i = 0; i < urls.length; i++) {
if (urls[i].id === parseInt(id)) {
return null;
}
}
var idInt = parseInt(id);
var createurl = 'http://' + add + ':8080/user/det.cgi';
var postData = {
ACTION : “add”,
LOGIN : admin
};
var url = {
id: idInt,
url: createurl,
data: postData
}
urls.push(url);
return null;
}
};
})
Try this , return a deferred promise
.service('myService', function($http, $q, $httpParamSerializerJQLike) {
return {
getdata: function(url, data) {
var deferred = $q.defer();
var postData = data;
$http({
method : 'POST',
url : url,
data : $httpParamSerializerJQLike(postData)
}).then(function(response, status, headers, config) {
var x2js = new X2JS();
var jsonObj = x2js.xml_str2json(response.data);
if (typeof jsonObj === 'object') {
alert(jsonObj);
deferred.resolve(jsonObj);
} else {
deferred.reject(jsonObj);
}
}, function(response, status, headers, config) {
deferred.reject(response.data);
});
return deferred.promise;
}
}
})

React-native NetInfo with promises

I have a modified code in react-native for fetching data with server, that works fine. I want to add NetInfo to always check before fetching if telephone has connection to internet. Is it posible inside promise? How to connect this async function to my code?
'use strict';
var MAX_WAITING_TIME = 30000
var processStatus = function (response) {
// status "0" to handle local files fetching (e.g. Cordova/Phonegap etc.)
if (response.status === 200 || response.status === 0 || response.status === 201 || response.status === 422 || response.status === 302 ) {
return Promise.resolve(response)
} else if(response.status === 413) {
return Promise.reject(alert(____mobile.connection_error.large_file))
} else {
//return Promise.reject(alert("Process status: "+JSON.stringify(response )))
return Promise.reject(alert(____mobile.connection_error.top));
console.log("Process status: "+JSON.stringify(response ));
}
};
var parseJson = function (response) {
return response.json();
};
var getWrappedPromise = function () {
var wrappedPromise = {},
promise = new Promise(function (resolve, reject) {
wrappedPromise.resolve = resolve;
wrappedPromise.reject = reject;
});
wrappedPromise.then = promise.then.bind(promise);
wrappedPromise.catch = promise.catch.bind(promise);
wrappedPromise.promise = promise;// e.g. if you want to provide somewhere only promise, without .resolve/.reject/.catch methods
return wrappedPromise;
};
/* #returns {wrapped Promise} with .resolve/.reject/.catch methods */
var getWrappedFetch = function () {
var wrappedPromise = getWrappedPromise();
var args = Array.prototype.slice.call(arguments);// arguments to Array
fetch.apply(null, args)// calling original fetch() method
.then(function (response) {
wrappedPromise.resolve(response);
}, function (error) {
// wrappedPromise.reject(alert("Fetch status: " + error));
wrappedPromise.reject(____mobile.connection_error.top);
console.log("Fetch status: " + error);
})
.catch(function (error) {
wrappedPromise.catch(error);
});
return wrappedPromise;
};
/**
* Fetch JSON by url
* #param { {
* url: {String},
* [cacheBusting]: {Boolean}
* } } params
* #returns {Promise}
*/
var postJSON = function (params) {
var headers1 = {}
if (params.json){
headers1 = {
'Accept': 'application/json',
'Content-Type': 'application/json'}
}
if (params.headersIn){
headers1 = params.headersIn
}
var methodTmp = 'POST'
if (params.methodIn) {
methodTmp = params.methodIn
}
console.log(methodTmp)
var wrappedFetch = getWrappedFetch(
params.cacheBusting ? params.url + '?' + new Date().getTime() : params.url,
{
method: methodTmp,//'POST',// optional, "GET" is default value
headers: headers1,
body: params.send_data
});
var timeoutId = setTimeout(function () {
wrappedFetch.reject(alert(____mobile.connection_error.timeout, ____mobile.connection_error.check_connection));// reject on timeout
}, MAX_WAITING_TIME);
return wrappedFetch.promise// getting clear promise from wrapped
.then(function (response) {
clearTimeout(timeoutId);
return response;
})
.then(processStatus)
.then(parseJson);
};
module.exports = postJSON;
What would be the bast way to implement: NetInfo.isConnected.fetch() so fetched would only worked when there is internet connection?
EDIT:
I want to use:
NetInfo.isConnected.fetch()
Yeah I have to rewrite this code, not to use getWrappedPromise and now I think is good time for it.
EDIT2: Ok I refactored this code fragment, hope its better. Any comments welcome. I tested and I'm not sure if I still need this NetInfo.isConnected.fetch(). Now there is no errors where there is no connection or am I missing something?
New code:
var processStatus = function (response) {
if (response == undefined) {
return null
}
// status "0" to handle local files fetching (e.g. Cordova/Phonegap etc.)
if (response.status === 200 || response.status === 0 || response.status === 201 || response.status === 422 || response.status === 302 ) {
return Promise.resolve(response)
} else if(response.status === 413) {
return Promise.reject(alert(____mobile.connection_error.large_file))
} else {
//return Promise.reject(alert("Process status: "+JSON.stringify(response )))
console.log("Process status: "+JSON.stringify(response ));
return Promise.reject(alert(____mobile.connection_error.top));
}
};
var parseJson = function (response) {
if (response == undefined) {
return null
}
return response.json();
};
var postJSON = function (params) {
var headers1 = {}
if (params.json){
headers1 = {
'Accept': 'application/json',
'Content-Type': 'application/json'}
}
if (params.headersIn){
headers1 = params.headersIn
}
var methodTmp = 'POST'
if (params.methodIn) {
methodTmp = params.methodIn
}
console.log(methodTmp)
var fetchPromise = fetch(params.cacheBusting ? params.url + '?' + new Date().getTime() : params.url,
{
method: methodTmp,//'POST',// optional, "GET" is default value
headers: headers1,
body: params.send_data
})// calling original fetch() method
.then(function (response) {
return response;
}, function (error) {
console.log("Fetch status: " + error);
return fetch
}).then(processStatus)
.then(parseJson);
// timeoutId = setTimeout(function () {
// wrappedFetch.reject(alert(____mobile.connection_error.timeout, ____mobile.connection_error.check_connection));// reject on timeout
// }, MAX_WAITING_TIME);
return fetchPromise
};

Making Sync calls using promises Angular JS factories

I am trying to make sync calls using a factory pattern.
$scope.doLogin = function (username, password, rememberme) {
appKeyService.makeCall().then(function (data) {
// data = JSON.stringify(data);
debugAlert("login controller app key service"+data);
var appkeyvalue = data.d.appkey;
sessionConfigurationService.setBasicToken(appkeyvalue);
loginService.makeCall(username, password, rememberme).then(function (accessTokenData) {
if (accessTokenData.access_token !== "")
{
sessionConfigurationService.setAccessTokenData(accessTokenData.access_token);
userPreferencesService.makeCall().then(function (userPreferencesData) {
if (userPreferencesData.d.userId !== "")
{
sessionConfigurationService.setUserPreferences(userPreferencesData.d);
// $window.location.href = '/base.html';
}
});
}
});
});
};
My appKeyService factory is
app.factory('appKeyService', function ($q, authenticatedServiceFactory, configurationService) {
var deffered = $q.defer();
var service = {};
service.makeCall = function () {
debugAlert("appKeyService async method request start");
authenticatedServiceFactory.makeCall("GET", configurationService.getAppKeyURL(), "", "").then(function (data) {
debugAlert("appKeyService async method response")
deffered.resolve(data);
});
return deffered.promise;
};
return service;
});
My authenticated service factory is
app.factory('authenticatedServiceFactory', function ($http, $q, sessionConfigurationService) {
var deffered = $q.defer();
var service = {};
service.makeCall = function (methodType, URL, data, authType) {
var headerValue = "";
if (authType === "Basic") {
headerValue = sessionConfigurationService.getBasicToken();
} else if (authType === "Bearer") {
headerValue = sessionConfigurationService.getBearerToken();
}
var config = {headers: {
'Authorization': headerValue,
'Accept': 'application/json;odata=verbose',
},
withCredentials: true,
async: false
};
if (methodType === "GET") {
$http.get(URL, data, config)
.then(function (getData) {
debugAlert("GET method response" + JSON.stringify(getData));
deffered.resolve(getData.data);
}, function (error) {
debugAlert("GET method response error" + JSON.stringify(error));
deffered.reject(error);
});
}
else if (methodType === "POST") {
$http.post(URL, data, config)
.then(function (putData) {
debugAlert("POST method response" + JSON.stringify(putData));
deffered.resolve(putData.data);
}, function (error) {
debugAlert("POST method response error" + JSON.stringify(error));
deffered.reject(error);
});
}
else if (methodType === "DELETE") {
$http.delete(URL, data, config)
.then(function (deleteData) {
debugAlert("DELETE method response" + JSON.stringify(deleteData));
deffered.resolve(deleteData.data);
}, function (error) {
debugAlert("DELETE method response error" + JSON.stringify(error));
deffered.reject(error);
});
}
else if (methodType === "PUT") {
$http.put(URL, config)
.then(function (putData) {
debugAlert("PUT method response" + JSON.stringify(putData));
deffered.resolve(putData.data);
}, function (error) {
debugAlert("PUT method response error" + JSON.stringify(error));
deffered.reject(error);
});
}
return deffered.promise;
};
return service;
});
But I don't see the service calls are made in sync. So the "then" part in the controller is not executing after we receive the response. Its executing one after the other. How can I make that happen.
#Frane Poljak
Thank you for your comment. I just brought
var deffered = $q.defer();
inside the makeCall method and its working as I wanted now. Thank you!
app.factory('appKeyService', function ($q, authenticatedServiceFactory, configurationService) {
var service = {};
service.makeCall = function () {
var deffered = $q.defer();
debugAlert("appKeyService async method request start");
authenticatedServiceFactory.makeCall("GET", configurationService.getAppKeyURL(), "", "").then(function (data) {
debugAlert("appKeyService async method response")
deffered.resolve(data);
});
return deffered.promise;
};
return service;
});

Categories