Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 28 additions & 12 deletions lib/processingChain.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ function ProcessingChain( ) {
}

ProcessingChain.prototype.add = function( proc ) {
proc.names = proc.names ?
( Array.isArray(proc.names) ? proc.names : Array(proc.names) )
: [];
if(proc.fn.length == 4) //it's an error handler
this.errorHandlers.push(proc);
else
Expand All @@ -23,9 +26,17 @@ ProcessingChain.prototype.pop = function() {
this.chain.pop();
}

ProcessingChain.prototype.runChain = function( req, res, finalFn, handler ) {
ProcessingChain.prototype.runChain = function( params ) {
params = params || {};
var req = params.req;
var res = params.res;
var finalFn = params.finalFn;
var handler = params.handler;
var endPrep = (params.endPrep && {fn: params.endPrep}) || []; //last preprocessor

var currentItem = 0;
var totalItems = this.chain.length;
var chain = [].concat(this.chain, endPrep);
var totalItems = chain.length;
var self = this;
if(totalItems == 0) {
if(typeof finalFn == 'function') finalFn(req, res);
Expand All @@ -42,18 +53,23 @@ ProcessingChain.prototype.runChain = function( req, res, finalFn, handler ) {
}

var next = function(err) {
var chain = self.chain;
//chain is taken from the closure
if ( err ) { //If there is an error, switch to the error handlers chain
chain = self.errorHandlers;
currentItem = -1;
totalItems = self.errorHandlers.length;
}
if ( currentItem < totalItems - 1 ) {
for(var idx = currentItem + 1; idx < chain.length; idx++) {
if( (chain[idx].names && chain[idx].names.indexOf(handler.name) != -1) || !chain[idx].names) {
break
var idx = ++currentItem;

if( handler && handler.name) {
for(; idx < chain.length; idx++) {
if( !chain[idx].names || ( ! chain[idx].names.length ) || ~chain[idx].names.indexOf(handler.name)) {
break
}
}
}
}

currentItem = idx
if(err) {
chain[currentItem].fn(err, req, res, nextError)
Expand All @@ -65,16 +81,16 @@ ProcessingChain.prototype.runChain = function( req, res, finalFn, handler ) {
}
}
if(handler) {
var firstItem = self.findFirstValidItem(handler.name)
var firstItem = self.findFirstValidItem(handler.name, chain)
firstItem.fn(req, res, next)
} else {
this.chain[0].fn(req, res, next )
chain[0].fn(req, res, next )
}
};

ProcessingChain.prototype.findFirstValidItem = function(name) {
if(!name) return this.chain[0]
return _.find(this.chain, function(item) {
ProcessingChain.prototype.findFirstValidItem = function(name, chain) {
if(!name) return chain[0]
return _.find(chain, function(item) {
if(item.names && Array.isArray(item.names) && item.names.length > 0) {
return item.names.indexOf(name) != -1
} else {
Expand Down
46 changes: 32 additions & 14 deletions lib/vatican.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ var http = require("http"),
handlerParser = require("./handlerParser"),
processingChain = require("./processingChain"),
mongoose = require("mongoose"),
_ = require("lodash");
_ = require("lodash"),
path = require("path");


module.exports = Vatican;
Expand Down Expand Up @@ -37,22 +38,20 @@ function Vatican(options) {
this.parseHandlers();
this.paths = [];
this.server = null;
this.totalPreprocessors = 0;
this.preprocessors = new processingChain();
this.postprocessors = new processingChain();
}

Vatican.prototype.preprocess = function(fn, endpointNames) {
this.preprocessors.add({fn: fn, names: endpointNames ? endpointNames : []})
this.totalPreprocessors = this.preprocessors.getTotal();
this.preprocessors.add({fn: fn, names: endpointNames})
}

Vatican.prototype.postprocess = function(fn, endpointNames) {
this.postprocessors.add({fn: fn, names: endpointNames ? endpointNames : []});
this.postprocessors.add({fn: fn, names: endpointNames});
}

Vatican.prototype.parseHandlers = function(cb) {
var dir = this.options.handlers;
var dir = path.isAbsolute(this.options.handlers) ? this.options.handlers : process.cwd() + "/" + this.options.handlers;
var self = this;
handlerParser.parse(dir, function(err, path) {
if(typeof cb == 'function' && err) return cb(err)
Expand Down Expand Up @@ -148,18 +147,20 @@ Vatican.prototype.requestHandler = function (req, res) {
} else {
try {
var request = this.createRequest(req);
var hdlr = this.loadHandler(process.cwd() + "/" + methodFound.handlerPath);
var hdlr = this.loadHandler(methodFound.handlerPath);
res = vaticanResp.improveResponse(res, request, this.options, this.postprocessors);
//Parse the request to grab the parameters
this.parseRequest(request, methodFound.url, req, function(newRequest) {
//Run the pre-process chain and finally, call the handler
if(self.preprocessors.getTotal() > self.totalPreprocessors) {
self.preprocessors.pop();
}
var hdlrInstance = new hdlr(self.getCorrectModel(methodFound))

hdlrInstance.models = self.dbmodels //Let the handler access all other models in case they're neeeded
self.preprocessors.add({fn: hdlrInstance[methodFound.action].bind(hdlrInstance)})
self.preprocessors.runChain(newRequest, res, null, methodFound);

self.preprocessors.runChain({
req: newRequest,
res: res,
handler: methodFound,
endPrep: hdlrInstance[methodFound.action].bind(hdlrInstance),
});
});
} catch (ex) {
logger.error("Error instantiating handler: " + ex.message);
Expand All @@ -171,7 +172,7 @@ Vatican.prototype.requestHandler = function (req, res) {

Vatican.prototype.getCorrectModel = function(handler) {
var modelName = handler.handlerName.replace("Hdlr", '')
return this.dbmodels[modelName]
return this.dbmodels && this.dbmodels[modelName]
}

/**
Expand All @@ -181,6 +182,7 @@ Vatican.prototype.start = function(cb) {
try {
this.server = http.createServer(this.requestHandler.bind(this));
this.server.listen(this.options.port);
console.log(this.server);
logger.info("Server started on port: " + this.options.port);
if(typeof cb == 'function') {
cb();
Expand All @@ -191,6 +193,22 @@ Vatican.prototype.start = function(cb) {
}
};

/**
Close the server
*/
Vatican.prototype.close = function(cb) {
try {
this.server.close();
logger.info("Server closed");
if(typeof cb == 'function') {
cb();
}
} catch (ex) {
logger.error("Error closing server: " + ex.message);
return false;
}
}

Vatican.prototype.dbStart = function(opts, cb) {
if(typeof opts === 'function') {
cb = opts
Expand Down
40 changes: 22 additions & 18 deletions lib/vaticanResponse.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,30 @@ VaticanResponse.prototype.send = function(txt) {
var headers = {};
var self = this;
this.body = txt;
this.ppChain.runChain(this.request, this, function(req, resp) {
//Check for CORS config
if(self.options.cors !== false) {
headers = _getCORSHeaders(self.options.cors);
}
this.ppChain.runChain({
req: this.request,
res: this,
finalFn: function(req, resp) {
//Check for CORS config
if(self.options.cors !== false) {
headers = _getCORSHeaders(self.options.cors);
}

//Adds the rest of the headers
for(var i in resp.headers) {
headers = _.assign(headers, resp.headers[i]);
}
//Adds the rest of the headers
for(var i in resp.headers) {
headers = _.assign(headers, resp.headers[i]);
}

//Write the headers
resp.response.writeHead(resp.statusCode, headers);
if( typeof resp.body == 'object') {
resp.body = JSON.stringify(resp.body);
}
//Write the headers
resp.response.writeHead(resp.statusCode, headers);
if( typeof resp.body == 'object') {
resp.body = JSON.stringify(resp.body);
}

//Write out the response text
resp.response.write(resp.body);
resp.response.end();
//Write out the response text
resp.response.write(resp.body);
resp.response.end();
},
})

};
Expand Down Expand Up @@ -95,4 +99,4 @@ function _getCORSHeaders(corsOpts) {
module.exports = {
improveResponse: _improveResponse,
writeNotFound: _writeNotFound
};
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"devDependencies": {
"should": "4.0.4",
"mocha": "1.21.4",
"supertest": "0.13.0",
"istanbul": "0.3.0"
}
}
6 changes: 6 additions & 0 deletions test/fixtures/vaticanConfig/handlers/people.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = People;
function People() {}
@endpoint (url: /people method: get)
People.prototype.getPeople = function(req, res) {
res.send('ok');
}
22 changes: 22 additions & 0 deletions test/fixtures/vaticanHttpMethods/handlers/people.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module.exports = People;
var peeps = [ 'user0', 'user1'];
function People() {}
@endpoint (url: /people method: get)
People.prototype.getPeople = function(req, res) {
res.send('get,' + peeps.join(','));
}

@endpoint (url: /people method: post)
People.prototype.postPeople = function(req, res) {
res.send('post,' + peeps.join(','));
}

@endpoint (url: /people method: put)
People.prototype.putPeople = function(req, res) {
res.send('put,' + peeps.join(','));
}

@endpoint (url: /people method: delete)
People.prototype.deletePeople = function(req, res) {
res.send('delete,' + peeps.join(','));
}
Loading