lds-connect-proxy
Version:
A node.js service to to proxy the ldsconnect.org API
138 lines (118 loc) • 3.6 kB
JavaScript
;
var request = require('request')
, apiEndpoints
// XXX Poor man's cache needs upgrading
, cache = {}
, staleAt = 60 * 60 * 1000
;
apiEndpoints = [
// need expansion
'/api/ldsorg/me'
, '/api/ldsorg/me/household'
, '/api/ldsorg/me/ward'
, '/api/ldsorg/me/stake'
// okay
, '/api/ldsorg/stakes/:stakeUnitNo/wards/:wardUnitNo/households/:householdId'
, '/api/ldsorg/stakes/:stakeUnitNo/wards/:wardUnitNo/photo-list'
, '/api/ldsorg/stakes/:stakeUnitNo/wards/:wardUnitNo/member-list'
, '/api/ldsorg/stakes/:stakeUnitNo/wards/:wardUnitNo/roster'
, '/api/ldsorg/stakes/:stakeUnitNo/wards/:wardUnitNo/info'
, '/api/ldsorg/stakes/:stakeUnitNo/wards/:wardUnitNo'
, '/api/ldsorg/stakes/:stakeUnitNo'
// new LDS Connect APIs
, '/api/ldsconnect/stakes/:stakeUnitNo/wards/:wardUnitNo/photos'
, '/api/ldsconnect/stakes/:stakeUnitNo/wards/:wardUnitNo/info'
, '/api/ldsconnect/stakes/:stakeUnitNo/photos'
, '/api/ldsconnect/stakes/:stakeUnitNo/info'
, '/api/ldsconnect/me'
];
function getCache(accessToken, mid, url, fn) {
url = url.replace(/ldsorg\/me(\b.*)/, 'ldsorg/' + mid + '$1');
fn(
null
, cache[accessToken]
&& cache[accessToken][url]
&& cache[accessToken][url].result
, cache[accessToken]
&& cache[accessToken][url]
&& cache[accessToken][url].updated);
}
module.exports.getCache = getCache;
function getUrl(mid, accessToken, url, fn) {
var options
;
options = {
//url: 'http://beta.ldsconnect.org:3000' + url
url: 'https://ldsconnect.org' + url
, headers: {
'Authorization': 'Bearer ' + accessToken
}
};
function callback(error, response, body) {
if (error || response.statusCode !== 200) {
fn(error || body, null);
return;
}
url = url.replace(/ldsorg\/me(\b.*)/, 'ldsorg/' + mid + '$1');
// TODO smarter, but still safe caching
cache[accessToken] = cache[accessToken] || {};
cache[accessToken][url] = {
updated: Date.now()
, result: JSON.parse(body)
};
clearTimeout(cache[accessToken].timeoutToken);
cache[accessToken].timeoutToken = setTimeout(function () {
delete cache[accessToken];
}, staleAt);
fn(null, body);
}
request(options, callback);
}
module.exports.getUrl = getUrl;
function forwardOauthRequest(retrieveToken, retrieveUid, req, res) {
var url = req.url
, accessToken = retrieveToken(req)
, mid = retrieveUid(req)
;
if (!accessToken || !mid) {
res.send({ error: { message: "Not logged in, duh!" } });
return;
}
getCache(accessToken, mid, req.url, function (err, result, updated) {
var now = Date.now()
//, url = req.url
;
function fin(body) {
body = body || '{ "error": "unknown error" }';
if (!body) {
console.error(req.url);
}
if ('string' === typeof body) {
res.end(body);
} else {
res.send(body);
}
}
if (!result) {
getUrl(mid, accessToken, url, function (err, data) {
fin(err && ('error: ' + err) || data);
});
} else if (now - updated > staleAt) {
getUrl(mid, accessToken, req.url, function (err, data) {
fin(err && ('error: ' + err) || data);
});
} else if (now - updated > staleAt / 2) {
getUrl(mid, accessToken, req.url, function () {});
fin(result);
} else {
fin(result);
}
});
}
module.exports.create = function (retrieveToken, retrieveUid) {
return function (rest) {
apiEndpoints.forEach(function (url) {
rest.get(url, forwardOauthRequest.bind(null, retrieveToken, retrieveUid));
});
};
};