identity
Version:
Identity client
214 lines (158 loc) • 6.41 kB
JavaScript
var restify = require('restify');
var URL = require('url');
var http = require('http');
module.exports = function(api, config){
//restify config
var identity_server = restify.createJsonClient({
url: config.site,
userAgent: api.config.general.serverName
});
//helper function
var startRequest = function(application, path, method, options, callback){
path = '/api/' + path;
//add the access_token
if(path.indexOf('?') !== -1){
path += '&access_token=' + application.access_token;
}else{
path += '?access_token=' + application.access_token;
}
var headers;
if(method === 'del'){
headers = {
'content-length': 0
};
}
//create restify instance
var app = restify.createJsonClient({
url: application.url,
userAgent: api.config.general.serverName,
headers: headers
});
api.logger.info('Request "' + path + '" of application "' + application.name + '" (' + application.url + ')');
//replace callback with a simpler version
if(typeof callback === 'function'){
var original = callback;
callback = function(err, req, res, resp){
original(err, resp, req, res);
}
}
//start request
if(options === null){
app[method](path, callback);
}else{
app[method](path, options, callback);
}
};
return function application(name, access_token){
var key = '__identity_application_' + name + (access_token || '');
return {
action: function(path, method, options, callback){
//get the current access_token for the application
this.getAccessToken(function(application){
if(application){
if(access_token && name === 'identity'){
//if there is a given access_token - use it inseatd
application.access_token = access_token;
}
startRequest(application, path, method, options, callback);
}else{
api.logger.error('did not get an access_token for application ' + name);
callback('did not get an access_token for application ' + name);
}
});
},
get: function(path, options, callback){
//put params into the url... restify wont do it for us :(
path = URL.format({pathname: path, query:options});
this.action(path, 'get', null, callback);
},
post: function(path, options, callback){
this.action(path, 'post', options, callback);
},
put: function(path, options, callback){
this.action(path, 'put', options, callback);
},
del: function(path, callback){
this.action(path, 'del', null, callback);
},
proxy: function(path, connection, next){
var req = connection.rawConnection.req;
var res = connection.rawConnection.res;
this.getAccessToken(function(application){
if(access_token && name === 'identity'){
//if there is a given access_token - use it inseatd
application.access_token = access_token;
}
path = '/api/' + path;
//add the access_token
if(path.indexOf('?') !== -1){
path += '&access_token=' + application.access_token;
}else{
path += '?access_token=' + application.access_token;
}
api.logger.info('Request "' + path + '" of application "' + application.name + '" (' + application.url + ')');
var options = {};
var uri = URL.parse(application.url);
options.hostname = uri.hostname;
options.path = path;
options.port = uri.port;
options.method = req.method;
var json = null;
if(req.method === 'POST'){
json = JSON.stringify(connection.rawConnection.params.body);
var len = Buffer.byteLength(json, 'utf8');
options.headers = {'content-type': req.headers['content-type'], 'content-length': len};
}
var newReq = http.request(options, function(newRes) {
var headers = newRes.headers;
delete headers['set-cookie'];
res.writeHead(newRes.statusCode, headers);
newRes.pipe(res).on('finish', function(){
next(connection, false);
});
}).on('error', function(err) {
res.statusCode = 500;
res.end();
});
if(json){
newReq.write(json);
}
newReq.end();
});
},
getAccessToken: function(callback){
//load the current access_token from our cache
api.cache.load(key, function(error, application){
if(application && application.access_token && application.expires_at > new Date().getTime()){
//return it
callback(application)
}else{
var url = '/api/application/access_token';
var params = {client_id: config.id, secret: config.secret, application_name: name};
if(name !== 'identity' && access_token){
url = '/api/user/access_token';
params = {access_token: access_token, application_name: name};
}
//ask identity server for a new token
identity_server.post(url, params , function(err, req, res, resp){
if(err || resp === null){
return callback(null);
}
var application = resp.application;
if(application && application.access_token){
var ttl = (application.ttl - 10) * 1000
application.expires_at = new Date().getTime() + ttl;
api.cache.save(key, application, ttl, function(error){
//TODO: error handling...
callback(application);
});
}else{
callback(null);
}
});
}
});
}
}
}
};