@incdevco/framework
Version:
node.js lambda framework
309 lines (175 loc) • 5.68 kB
JavaScript
var Util = require('util');
var Promise = require('bluebird');
var Base = require('../index');
var Request = require('./request');
var Response = require('./response');
function Lambda(config) {
'use strict';
Base.call(this, config);
this.console = config.console || console;
this.logger = config.logger || console;
this.routes = [];
this.useOriginalPath = (config.useOriginalPath) ?
true : false;
}
Util.inherits(Lambda, Base);
Lambda.prototype.handleException = function (exception, event, request, response) {
'use strict';
this.log(exception, exception.stack);
response.statusCode = 500;
if (typeof response.body === 'string') {
response.body = {};
}
response.body.message = 'An Error Occurred';
if (exception.message === 'Not Found'
|| exception.message === 'Not Allowed'
|| exception.code === 'ConditionalCheckFailedException') {
throw exception;
} else {
throw new Error('An Error Occurred');
}
//return true;
//throw response;
};
Lambda.prototype.handler = function (event, context) {
'use strict';
var request, response, self = this;
request = new Request(self, event);
response = new Response();
this.log('original-event', JSON.stringify(event, null, 2));
Promise.try(function () {
return self.route(event, request, response);
})
.then(function () {
return self.pre(event, request, response);
})
.then(function () {
return request.handler(event, request, response);
})
.then(function () {
self.log('pre post response', Util.inspect(response));
return self.post(event, request, response);
})
.catch(function (exception) {
return self.handleException(exception, event, request, response);
})
.then(function () {
/*
if (typeof response.body !== 'string') {
response.body = JSON.stringify(response.body);
}
*/
self.log('final response', Util.inspect(response));
context.succeed(response.body);
})
.catch(function (exception) {
context.fail(exception);
});
};
Lambda.prototype.log = function () {
'use strict';
this.console.log.apply(this.console, arguments);
};
Lambda.prototype.options = function (event, request, response) {
'use strict';
response.headers['Access-Control-Allow-Headers'] = 'authorization, content-type, x-amz-date, x-amz-security-token, x-api-key';
response.headers['Access-Control-Allow-Methods'] = 'DELETE,POST,PUT';
response.headers['Access-Control-Allow-Origin'] = '*';
response.body = '';
return Promise.resolve(true);
};
Lambda.prototype.pre = function (event, request, response) {
'use strict';
return this.Promise.resolve(true);
};
Lambda.prototype.Promise = Promise;
Lambda.prototype.post = function (event, request, response) {
'use strict';
return this.Promise.resolve(true);
};
Lambda.prototype.register = function (path, method, handler) {
if (this.useOriginalPath) {
return this.registerWithOriginalPath(path, method, handler);
} else {
return this.registerWithPath(path, method, handler);
}
};
Lambda.prototype.registerWithOriginalPath = function (path, method, handler) {
var route = {
handler: handler,
method: method,
params: {},
path: path,
regex: path
};
this.routes.push(route);
return this;
};
Lambda.prototype.registerWithPath = function (path, method, handler) {
var params = path.match(/:([^\/]+)/ig);
var route = {
handler: handler,
method: method,
params: params,
path: path,
regex: path
};
if (route.params) {
route.params.forEach(function (param) {
route.regex = route.regex.replace(param, '([a-zA-Z0-9-%]+)');
});
}
route.regex = new RegExp('^' + route.regex + '$', 'i');
this.routes.push(route);
return this;
};
Lambda.prototype.route = function (event, request) {
'use strict';
if (request.method === 'OPTIONS') {
request.handler = this.options.bind(this);
return Promise.resolve(true);
}
this.log('request', JSON.stringify(request, null, 2));
if (this.useOriginalPath) {
return this.routeWithOriginalPath(event, request);
} else {
return this.routeWithPath(event, request);
}
};
Lambda.prototype.routeWithOriginalPath = function (event, request) {
'use strict';
var match;
for (var i = this.routes.length; i--; ) {
if (this.routes[i].method === request.method) {
if (this.routes[i].path === request.originalPath) {
match = true;
request.handler = this.routes[i].handler;
}
}
}
if (match) {
return Promise.resolve(true);
} else {
return Promise.reject(new Error('Not Found'));
}
};
Lambda.prototype.routeWithPath = function (event, request) {
'use strict';
var match, test;
for (var i = this.routes.length; i--; ) {
if (this.routes[i].method === request.method) {
test = this.routes[i].regex.exec(request.path);
if (test !== null && test[0] === request.path) {
match = true;
//this.log('match', test[0]);
request.handler = this.routes[i].handler;
}
}
}
if (match) {
return Promise.resolve(true);
} else {
return Promise.reject(new Error('Not Found'));
}
};
module.exports = Lambda;