Last active
November 18, 2015 13:40
-
-
Save joewright/14e93b4de285bdc1adb0 to your computer and use it in GitHub Desktop.
PokitDok API Titanium example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*** | |
* Ti PD API | |
* | |
* App.config -> global config namespace | |
* we connect to a proxy instead of the API directly | |
* to avoid storing credentials on the client | |
* | |
* | |
* // Example api request | |
* api.request({ | |
* method: 'GET', | |
* path: '/businesses', | |
* callback: function (err, res) {}); | |
* | |
*/ | |
var refreshActive = false, | |
retryQueue = []; | |
/*** | |
* make an api call to pokitdok | |
* @param args | |
* @returns {*} | |
*/ | |
exports.request = function (args) { | |
if (Ti.Network.online === false) { | |
// network unavailable message i18n | |
alert(L('networkUnavailableBody')); | |
return args.callback(true, L('networkUnavailableBody')); | |
} | |
var client = Ti.Network.createHTTPClient({ | |
// hande 2XX response codes | |
onload: function (e) { | |
// Ti.API.info('Request: ' + args.method + ':' + url + ' ' + this.status); | |
// the UI can only process valid JSON | |
try { | |
var resJSON = JSON.parse(this.responseText); | |
// Ti.API.info(resJSON); | |
args.callback(null, resJSON); | |
} catch (e) { | |
Ti.API.info('JSON parse failure: ', e); | |
args.callback(true, { | |
message: this.responseText, | |
status: this.status | |
}); | |
} | |
}, | |
// handle non 2XX response codes | |
onerror: function (e) { | |
Ti.API.error('Request: ' + args.method + ':' + url + ' ' + this.status); | |
Ti.API.error('Request: ' + args.method + ':' + url + ' ' + this.responseText); | |
// auto-refresh the oauth token | |
if (this.status == 400 || this.status == 401) { | |
return refreshToken(args); | |
} | |
// the UI can only process valid JSON | |
try { | |
var resJSON = JSON.parse(this.responseText); | |
return args.callback(true, resJSON); | |
} catch (e) { | |
return args.callback(true, { | |
message: this.responseText, | |
status: this.status | |
}); | |
} | |
}, | |
// kill long lived requests | |
timeout: App.config.HTTP_TIMEOUT | |
}); | |
// open Request | |
var url = App.config.API_PROXY_URL + args.path; | |
client.open(args.method, url); | |
// attach the oauth bearer token | |
var accessToken = Ti.App.Properties.getString('accessToken', false); | |
if (accessToken) { | |
client.setRequestHeader('Authorization', 'Bearer ' + accessToken); | |
} | |
// make sure POST data is JSON | |
if (args.data) { | |
client.setRequestHeader('Content-Type', 'application/json'); | |
} | |
// send the current version | |
client.setRequestHeader('X-App-Version', 'iOS.' + App.config.VERSION); | |
// send Request | |
Ti.API.info('\n\n\nSending Reqest:' + App.config.API_PROXY_URL + args.path); | |
args.data && Ti.API.info(args.data); | |
(args.data) ? client.send(JSON.stringify(args.data)) : client.send(); | |
// return the HTTP client for cancellation | |
return client; | |
}; | |
/*** | |
* refresh a users oauth2 token and retry | |
* the api request | |
* @param requestArgs | |
*/ | |
function refreshToken(requestArgs) { | |
// protect against parallel refreshes | |
retryQueue.push(requestArgs); | |
if (refreshActive) { | |
return false; | |
} | |
var client = Ti.Network.createHTTPClient({ | |
// hande 2XX response codes | |
onload: function (e) { | |
Ti.API.info('Request: POST:/oauth2/token ' + this.status); | |
// the UI can only process valid JSON | |
try { | |
var resJSON = JSON.parse(this.responseText); | |
// replace the existing oauth tokens | |
Ti.App.Properties.setString('accessToken', resJSON.access_token); | |
Ti.App.Properties.setString('refreshToken', resJSON.refresh_token); | |
// retry any queued requests | |
while (0 < retryQueue.length) { | |
exports.request(retryQueue.pop()); | |
} | |
refreshActive = false; | |
} catch (e) { | |
requestArgs.callback(true, { | |
message: this.responseText, | |
status: this.status | |
}); | |
// disable additional requests | |
refreshActive = false; | |
retryQueue = []; | |
// kill the sesssion on any refresh errors | |
if (Ti.App.Properties.getString('accessToken')) { | |
App.fireEvent('logout'); | |
} | |
} | |
}, | |
// handle non 2XX response codes | |
onerror: function (e) { | |
Ti.API.error('Request: POST:/refresh-token ' + this.status); | |
// the UI can only process valid JSON | |
try { | |
var resJSON = JSON.parse(this.responseText); | |
requestArgs.callback(true, resJSON); | |
} catch (e) { | |
requestArgs.callback(true, { | |
message: this.responseText, | |
status: this.status | |
}); | |
} | |
// disable additional requests | |
refreshActive = false; | |
retryQueue = []; | |
// kill the sesssion on any refresh errors | |
if (Ti.App.Properties.getString('accessToken')) { | |
App.fireEvent('logout'); | |
} | |
}, | |
// kill long lived requests | |
timeout: App.config.HTTP_TIMEOUT | |
}); | |
// open Request | |
client.open('POST', App.config.API_PROXY_URL + '/refresh-token'); | |
// only send JSON | |
client.setRequestHeader('Content-Type', 'application/json'); | |
// send the current version | |
client.setRequestHeader('X-App-Version', 'iOS.' + App.config.VERSION); | |
// send the request | |
client.send(JSON.stringify({ | |
refresh_token: Ti.App.Properties.getString('refreshToken', '') | |
})); | |
// protect against parallel refreshes | |
refreshActive = true; | |
return client; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment