Developing node-mdb: a Node.js - based clone of SimpleDB
1. Developing node-mdb SimpleDB emulation using Node.js and GT.M Rob Tweed M/Gateway Developments Ltd http://www.mgateway.com Twitter: @rtweed
2.
3.
4.
5.
6.
7.
8.
9.
10. How does SimpleDB work? HTTP Server Authenticate Request (HMacSHA) Security Key Id Secret Key Execute API Action Generate HTTP Response SimpleDB Database Copy 1 SimpleDB Database Copy 2 SimpleDB Database Copy n SimpleDB Database Copy 2 SimpleDB Database Copy 2 Incoming SDB HTTP Request Outgoing SDB HTTP Response Error Success and/or data/results
11. Node.js can emulate all this HTTP Server Authenticate Request (HMacSHA) Security Key Id Secret Key Execute API Action Generate HTTP Response SimpleDB Database Copy 1 SimpleDB Database Copy 2 SimpleDB Database Copy n SimpleDB Database Copy 2 SimpleDB Database Copy 2 Incoming SDB HTTP Request Outgoing SDB HTTP Response Error Success and/or data/results
12. GT.M can emulate this HTTP Server Authenticate Request Security Key Id Secret Key Execute API Action Generate HTTP Response SimpleDB Database Copy 1 Incoming SDB HTTP Request Outgoing SDB HTTP Response Error Success and/or data/results
13.
14. Result: deeply nested call-backs HTTP Server Authenticate Request Security Key Id Secret Key Execute API Action Generate HTTP Response Error Success and/or data/results
15. Flattening the call-back nesting processSDBRequest() http server executeAPI() sendResponse() http.createServer(function(req,res) {..} var processSDBRequest = function() {…}; var executeAPI = function() {…};
16. Node.js HTTP Server http.createServer(function(request, response) { request.content = ''; request.on("data", function(chunk) { request.content += chunk; }); request.on("end", function(){ var SDB = {startTime: new Date().getTime(), request: request, response: response }; var urlObj = url.parse(request.url, true); if (request.method === 'POST') { SDB.nvps = parseContent(request.content); } else { SDB.nvps = urlObj.query; } var uri = urlObj.pathname; if ((uri.indexOf(sdbURLPattern) !== -1)||(uri.indexOf(mdbURLPattern) !== -1)) { processSDBRequest(SDB); } else { var uriString = 'http://' + request.headers.host + request.url; var error = {code:'InvalidURI', message: 'The URI ' + uriString + ' is not valid',status:400}; returnError(SDB ,error); } }); }).listen(httpPort);
17. processSDBRequest() var processSDBRequest = function(SDB) { var accessKeyId = SDB.nvps.AWSAccessKeyId; if (!accessKeyId) { var error = {code:'AuthMissingFailure', message: 'AWS was not able to authenticate the request: access credentials are missing',status:403}; returnError(SDB, error); } else { MDB.getGlobal('MDBUAF', ['keys', accessKeyId], function (error, results) { if (!error) { if (results.value !== '') { accessKey[accessKeyId] = results.value; validateSDBRequest(SDB, results.value); } else { var error = {code:'AuthMissingFailure', message: 'AWS was not able to authenticate the request: access credentials are missing',status:403}; returnError(SDB, error); } } }); } };
18. validateSDBRequest() var validateSDBRequest = function(SDB, secretKey) { var type = ‘HmacSHA256’; var stringToSign = createStringToSign(SDB, true); var hash = digest(stringToSign, secretKey, type); if (hash === SDB.nvps.Signature) { processSDBAction(SDB); } else { errorResponse('SignatureDoesNotMatch', SDB) } };
19. stringToSign() POST {lf} 192.168.1.134:8081 {lf} / {lf} AWSAccessKeyId= rob &Action=ListDomains& MaxNumberOfDomains=100&SignatureMethod=HmacSHA1& SignatureVersion=2& Timestamp=2011-06-06T22%3A39%3A30%2 B00%3A00& Version=2009-04-15 ie: reconstruct the same string that the SDB client used to sign the request then use rob ’s secret key to sign it:
20. digest() var crypto = require("crypto"); var digest = function(string, secretKey, type) { var hmac = crypto.createHmac(type, secretKey); hmac.update(string); return hmac.digest('base64'); };
21. Ready to execute an API! HTTP Server Authenticate Request Security Key Id Secret Key Execute API Action Generate HTTP Response SimpleDB Database Copy 1 SimpleDB Database Copy 2 SimpleDB Database Copy n SimpleDB Database Copy 2 SimpleDB Database Copy 2 Incoming SDB HTTP Request Outgoing SDB HTTP Response Error Success and/or data/results